ADR-0015: Commercial web ecosystem, human/machine plane separation, licensing
Status: Accepted · 2026-07-15 (applies handoff update-001)Context
Update-001 (find_my_data_handoff/FIND_MY_DATA_CLAUDE_UPDATE_001/) adds the
commercial web and customer lifecycle around the customer-hosted platform:
marketing, account portal, licensing, entitled downloads, support, an isolated
demo, a protected dev environment, and Cloudflare domain management. The core
invariant is unchanged and reinforced: customer content never leaves the
customer boundary to license or support the product.
Decisions
1. Two planes, never merged: customer content plane vs. vendor commercial/control plane
The installed Find My Data platform (this repository) runs inside the customer’s Azure environment and holds all content, evidence, findings, identities, and Analyst conversations. The vendor operates a separate commercial/control plane for accounts, evaluations, licensing, downloads, support, and minimized fleet health. Content, excerpts, filenames, paths, fingerprints, embeddings, identities, permissions, findings, and prompts do not cross into the vendor plane. Enforced in code by the strictly-allowlisted telemetry schema (controlplane/telemetry.ts, .strict() + denylist test) and by keeping the
control-plane surface to licensing + coarse health only.
2. Human Account plane ≠ machine Control plane ≠ in-product roles
Three identity contexts stay distinct:account.findmydata.io (people —
commercial org, evaluations, downloads), control.findmydata.io (installed
software + scanners — activation, signed entitlement renewal, allowlisted fleet
health), and the capability roles inside each customer deployment (ADR-0004,
capabilities.ts). A human portal token is never the product’s license
credential. This build implements the deployment side of the Control contract;
the vendor-hosted Account/Control services are out of this repository’s scope
(they hold the signing private keys).
3. No app.findmydata.io
The product is customer-hosted with a customer-controlled URL and identity
context. app.findmydata.io would imply a shared SaaS data plane that does not
match the architecture; it is reserved, not built.
4. Signed, versioned entitlements verified locally (ADR extends the control plane)
Entitlements are signed by Control and verified locally by the deployment (controlplane/entitlement.ts). Two verification algorithms selected by the
token header:
- Ed25519 — the production shape: the deployment embeds/trusts only the vendor public key; the signing private key never leaves the hardened vendor service.
- HMAC — a runnable dev/test default.
kid so they rotate; the entitlement is versioned
(entitlementVersion) and expresses edition, feature flags, capacity meters,
term, connector families, offline/renewal policy, issuer, and a supersession
reference. Activation stores a verified token (an auditable offline path is
first-class; the live outbound path is gated on controlUrl). Renewal
re-verifies and reports the next-due time within a grace window.
5. Non-destructive expiry
Past the offline grace window an entitlement isexpired, which the enforcement
layer (assertLicensedOperation, LicenseError 402) treats as “no new licensed
operations” (e.g. starting a new scan). It never deletes, encrypts, or locks
the customer’s own configuration, findings, audit, or export. Unlicensed (no
entitlement configured) is permissive so the product runs unrestricted until a
customer activates a license.
6. Marketing/web surfaces are documented + minimally scaffolded, not prioritized over core
Per update-001’s explicit guidance, a marketing-site build must not displace core product work. This build adds a single self-contained static landing page (site/index.html) that is brand-consistent and honest (customer-hosted, not a
consumer locator), plus the web-ecosystem architecture in the design set and a
Cloudflare domain runbook. The Account portal, Support platform, Demo instance,
and live Cloudflare changes are captured as design + roadmap, not built here.
7. Cloudflare: documented, reversible, inspect-first — no unattended live changes
The domain runbook (docs/cloudflare-runbook.md) records the intended DNS,
redirect, and Access posture with inspect-first discipline and rollback notes.
No live Cloudflare changes are made without explicit per-change confirmation;
registrar ownership, transfer lock, DNSSEC, recovery contacts, and email
delivery are preserved.
Consequences
- The licensing/control-plane code now matches the commercial design (§6 of the new web-account-licensing design doc), while the content boundary stays an enforced invariant.
- The commercial web ecosystem is architecturally captured and lightly
scaffolded; the heavy vendor-side services remain future work, honestly staged
in
STATUS.mdanddocs/roadmap.md. - Product versioning is unchanged (
year.month.day.x); this update is release 26.7.15.1 (a same-day increment over 26.7.15.0).