Status: Proposed Date: 2026-09-23 Related: Architecture Review §4.17, G-23, ADR-A51, ADR-A54 Drafted by: Agent, autonomous session (P0.1.8). Pending human ratification — see phase-0-status.md.
The existing single GraphReference type conflates two distinct scoping axes: the design-time grouping under which a pack is authored, and the runtime environment it is activated into. This blocks the vendor-ships-pack-to-customer case (a pack built in project P activated into environments E₁…Eₙ, possibly belonging to different tenants) and leaves projectId/environmentId doing both jobs implicitly.
Organisation
└── Tenant (isolation boundary; owns datasets, quotas, entitlements)
├── Project (design-time grouping: contracts, mappings, packs) [existing]
└── Environment (runtime: dev | test | staging | prod | per-tenant custom)
├── DatasetBinding (store kind, URI, capability report)
└── ActivationBinding (pack in force) [C-02]
projectId scopes authoring. environmentId scopes running. These are stated as distinct from this ADR onward — no component may use one where the other is required.
GraphReferenceAuthoredGraphReference(tenant, project, revisionIri, hash)
RuntimeGraphReference(tenant, environment, graphIri, generation)
revisionHash on AuthoredGraphReference is a verification field (ADR-A51), not an identity field. GraphMaterializer’s hash check verifies exactly what it claims once this split lands.
GraphReference with these two types; a mismatched revision hash raises GraphMaterializationError before any compiler invocation; a runtime reference cannot be used where an authored one is required (enforced at the type level).