Skip to main content
Status: accepted · ADR-36 · Filed 2026-04-30

Title

Reserved-seams pattern: schema columns present in v1 with no consumer, sized to absorb future SPEC additions without re-plumbing

Decision

Apply a “reserved-seams” pattern in SPEC-056 schema: include columns and naming conventions that have no consumer in the immediate scope but are sized to absorb specific named future work without schema migration. Specifically:
  • agents.agent_service_id UUID NULL — reserved for the future Enterprise Agent Services catalogue. No FK target table created in v1; column sits NULL on every row.
  • users.github_login TEXT NULL — reserved for the future GitHub-invite cross-network collaboration flow.
  • signal_queue.from_user_id + from_agent_session — reserved for cross-tenant audit trail when project_memberships ship.
  • Channel naming includes tenant_id qualifier even where same-tenant subscription is the only path today (prism:events:project:{tenant}:{org}:{project}) — reserves space for cross-tenant project access via memberships without channel rename.
  • Header X-Prism-User-Id carried in v1 even though Personal Install has one user; reserves space for multi-user-per-tenant onboarding (Joe joins Frank’s Personal Install).
Each reserved seam is documented in SPEC-056 §Reserved seams with a named target SPEC. Columns are added with explicit comments in the schema migration explaining what they’re for and which future spec consumes them. The seams are NOT covered by tests in v1 (nothing to test — no consumer); they are covered by tests when the consuming SPEC ships.

Rationale

Schema migrations on a multi-tenant production system carry meaningful coordination cost: data backfill, downtime windows, follow-up cleanup. Each future feature (cross-tenant memberships, agent catalogue, GitHub invites) would otherwise require its own schema migration touching the same hot tables (agents, users, signal_queue). Doing them once with explicit reserved seams gives:
  1. One migration, multiple downstream specs. Future-spec implementers add behavior + tests, not schema.
  2. Explicit named coupling. Each seam is in the SPEC; git grep for the column name surfaces every place the future-spec author needs to touch.
  3. Lower regression risk. Future migrations don’t have to recompute backfill across the same tables.
The pattern is constrained — only seams that are already named in the running TODO list are reserved. We don’t speculatively add columns “in case.” Frank’s feedback_optimize_later rule applies to architecture too: don’t reserve seams for hypothetical futures, only for explicitly-listed future SPECs (catalogue, memberships, invites, deployment-modes).

Alternatives Considered

  1. No reserved seams; let each future SPEC do its own schema migration. Operationally simpler now, harder later. Each future spec touches the same hot tables independently — three migrations instead of one, with risk of conflicting column naming or backfill assumptions.
  2. Reserve broadly — every plausible future feature gets a column. Speculative; violates feedback_optimize_later. The pattern only works if seams are tightly scoped to named-and-prioritized future SPECs.
  3. Reserved seams as separate migration, run later. Same operational cost as separate spec migrations; loses the “do it once” benefit.

Status

accepted

References

  • SPEC-056 §Reserved seams
  • Memories: project_future_enterprise_agent_services, project_future_github_invite_collab, project_future_cross_internet_deployment_modes, feedback_optimize_later
Last modified on May 3, 2026