ARCH-01 — Principal equivalence classes, conflict detection, and serialized merges #824

Open
opened 2026-07-22 19:42:25 -05:00 by jcwalker3 · 0 comments
Owner

Candidate architecture requiring executable validation; not yet approved, production-ready, or certified.

Parents: #820, #821. Depends on: #822 (class root + current_class_id).

1. Summary / objective

Implement principal equivalence: one current class per principal, append-only merge/linkage history, a full cross-class conflict scan before any merge, serialized merges, and permanent same_principal decisions.

2. Security/correctness problem

Equivalence decides whether two transport identities are "the same actor" for separation-of-duties. A wrong or racing merge collapses distinct actors (defeating SoD) or contradicts a prior distinctness proof.

3. Threat model / failure modes

Same-issuer ids merged as one; a merge that ignores a distinct decision between non-named members of the two classes; concurrent crossing merges; direct current_class_id rewrite; superseding a permanent same-decision; cyclic/redirected superseded_by.

4. In-scope behavior

  • principals.current_class_id NOT NULL FK (one current class). [SCHEMA].
  • principal_linkages(principal_a<principal_b, disposition∈{same,distinct}, evidence_id, status∈{active,superseded}, supersedes), UNIQUE(a,b) WHERE status='active'; unlimited immutable historical rows. [SCHEMA].
  • Permitted issuer combinations (closed table): same authoritative issuer ⇒ same_principal forbidden; cross-transport / transport↔operator_key / cross-key permitted with the matching evidence reference_kind. [SCHEMA] trigger.
  • merge_equivalence (merge mode only): resolve classes; equal→no-op; full transitive scan of every active distinct_principal across the two complete member sets → EQUIVALENCE_CONTRADICTION on any hit; canonical survivor = lower class_id; rewrite absorbed members' current_class_id (permitted only in merge mode); set absorbed class superseded_by; insert same_principal active.
  • Membership change only via merge (principal_immutable exempts current_class_id only in merge mode). [SCHEMA].
  • same_principal permanent (no_supersede_same); only distinct_principal may be superseded, same canonical pair, one transaction. class_supersede_acyclic. [SCHEMA].

5. Exclusions

No cross-repository identity, no evidence-record creation (consumes existing valid records), no UI.

6. Schema/operation contracts

principal_equivalence_classes, principal_class_members (or current_class_id on principals — implement whichever the executable design proves cleaner; the NOT NULL single-value guarantee is required), principal_linkages. Operations: merge_equivalence, record_distinct_principal.

7. SQLite behavior

BEGIN IMMEDIATE; survivor = lower id; the transitive scan reads both complete member sets before writing.

8. PostgreSQL behavior

SERIALIZABLE; SELECT … FOR UPDATE on both class rows in deterministic id order; retry on serialization failure; concurrent crossing merges cannot both commit.

9. Concurrency / transaction requirements

Deterministic lock order prevents deadlock; two concurrent merges touching overlapping classes serialize; a merge contradicted by an existing distinct decision is rejected, not silently overridden.

10. Structured results

MERGED, MERGE_NOOP, EQUIVALENCE_CONTRADICTION, LINKAGE_ISSUER_FORBIDDEN, SUPERSEDE_SAME_FORBIDDEN, SERIALIZATION_RETRY, AUTHORIZATION_DENIED.

11. Enforcement classification

NOT NULL class, active-linkage uniqueness, issuer rule, acyclic supersede, no-supersede-same [SCHEMA]; digest of evidence subject [TRUSTED-SERVICE] (from the evidence issue); merge serialization [TRUSTED-SERVICE]/backend locks.

12. Acceptance criteria

  1. Every principal has exactly one current class.
  2. Same-issuer ids cannot be same_principal.
  3. Each cross-issuer link requires its declared proof kind.
  4. same_principal inserted only via merge_equivalence.
  5. Merge refused on any transitive distinct across the complete classes.
  6. same_principal decisions permanent; only distinct superseded (same pair, one txn).
  7. current_class_id not directly editable (except merge mode).
  8. Concurrent crossing merges cannot both commit.
  9. superseded_by acyclic, no redirect.

13. Named tests

t_one_class(+), t_same_issuer_same(−), t_cross_issuer_wrong_proof(−), t_direct_same_insert(−/raw-bypass), t_merge_transitive_conflict(−), t_supersede_same(−), t_direct_class_edit(raw-bypass), t_concurrent_crossing_merge(concurrency, both backends), t_supersede_cycle(−).

14. Audit events / evidence

equivalence_merged, equivalence_contradiction, distinct_recorded, linkage_superseded. Test-run output is evidence.

15. Dependencies / parent

Parents #820, #821; depends on #822; consumes evidence records from the typed-evidence issue (linkage proofs).

16. Definition of done

Executable on SQLite and PostgreSQL; ACs pass incl. concurrency + raw-bypass; bounded PR; no self-review/merge.

17. Known limitations / deferred

Class splitting is unsupported (merges permanent). Reversing a wrong same-decision requires operator-level re-provisioning of the principals — out of scope; note as a follow-up if needed.

**Candidate architecture requiring executable validation; not yet approved, production-ready, or certified.** Parents: #820, #821. Depends on: #822 (class root + `current_class_id`). ## 1. Summary / objective Implement principal equivalence: one current class per principal, append-only merge/linkage history, a full cross-class conflict scan before any merge, serialized merges, and permanent `same_principal` decisions. ## 2. Security/correctness problem Equivalence decides whether two transport identities are "the same actor" for separation-of-duties. A wrong or racing merge collapses distinct actors (defeating SoD) or contradicts a prior distinctness proof. ## 3. Threat model / failure modes Same-issuer ids merged as one; a merge that ignores a distinct decision between non-named members of the two classes; concurrent crossing merges; direct `current_class_id` rewrite; superseding a permanent same-decision; cyclic/redirected `superseded_by`. ## 4. In-scope behavior - `principals.current_class_id` NOT NULL FK (one current class). `[SCHEMA]`. - `principal_linkages(principal_a<principal_b, disposition∈{same,distinct}, evidence_id, status∈{active,superseded}, supersedes)`, `UNIQUE(a,b) WHERE status='active'`; unlimited immutable historical rows. `[SCHEMA]`. - Permitted issuer combinations (closed table): same authoritative issuer ⇒ `same_principal` forbidden; cross-transport / transport↔operator_key / cross-key permitted with the matching evidence `reference_kind`. `[SCHEMA]` trigger. - `merge_equivalence` (merge mode only): resolve classes; equal→no-op; **full transitive scan** of every active `distinct_principal` across the two complete member sets → `EQUIVALENCE_CONTRADICTION` on any hit; canonical survivor = lower `class_id`; rewrite absorbed members' `current_class_id` (permitted only in merge mode); set absorbed class `superseded_by`; insert `same_principal` active. - Membership change only via merge (`principal_immutable` exempts `current_class_id` only in merge mode). `[SCHEMA]`. - `same_principal` permanent (`no_supersede_same`); only `distinct_principal` may be superseded, same canonical pair, one transaction. `class_supersede_acyclic`. `[SCHEMA]`. ## 5. Exclusions No cross-repository identity, no evidence-record creation (consumes existing valid records), no UI. ## 6. Schema/operation contracts `principal_equivalence_classes`, `principal_class_members` (or `current_class_id` on principals — implement whichever the executable design proves cleaner; the NOT NULL single-value guarantee is required), `principal_linkages`. Operations: `merge_equivalence`, `record_distinct_principal`. ## 7. SQLite behavior `BEGIN IMMEDIATE`; survivor = lower id; the transitive scan reads both complete member sets before writing. ## 8. PostgreSQL behavior `SERIALIZABLE`; `SELECT … FOR UPDATE` on both class rows in deterministic id order; retry on serialization failure; concurrent crossing merges cannot both commit. ## 9. Concurrency / transaction requirements Deterministic lock order prevents deadlock; two concurrent merges touching overlapping classes serialize; a merge contradicted by an existing distinct decision is rejected, not silently overridden. ## 10. Structured results `MERGED`, `MERGE_NOOP`, `EQUIVALENCE_CONTRADICTION`, `LINKAGE_ISSUER_FORBIDDEN`, `SUPERSEDE_SAME_FORBIDDEN`, `SERIALIZATION_RETRY`, `AUTHORIZATION_DENIED`. ## 11. Enforcement classification NOT NULL class, active-linkage uniqueness, issuer rule, acyclic supersede, no-supersede-same `[SCHEMA]`; digest of evidence subject `[TRUSTED-SERVICE]` (from the evidence issue); merge serialization `[TRUSTED-SERVICE]`/backend locks. ## 12. Acceptance criteria 1. Every principal has exactly one current class. 2. Same-issuer ids cannot be `same_principal`. 3. Each cross-issuer link requires its declared proof kind. 4. `same_principal` inserted only via `merge_equivalence`. 5. Merge refused on any transitive distinct across the complete classes. 6. `same_principal` decisions permanent; only distinct superseded (same pair, one txn). 7. `current_class_id` not directly editable (except merge mode). 8. Concurrent crossing merges cannot both commit. 9. `superseded_by` acyclic, no redirect. ## 13. Named tests `t_one_class`(+), `t_same_issuer_same`(−), `t_cross_issuer_wrong_proof`(−), `t_direct_same_insert`(−/raw-bypass), `t_merge_transitive_conflict`(−), `t_supersede_same`(−), `t_direct_class_edit`(raw-bypass), `t_concurrent_crossing_merge`(concurrency, both backends), `t_supersede_cycle`(−). ## 14. Audit events / evidence `equivalence_merged`, `equivalence_contradiction`, `distinct_recorded`, `linkage_superseded`. Test-run output is evidence. ## 15. Dependencies / parent Parents #820, #821; depends on #822; consumes evidence records from the typed-evidence issue (linkage proofs). ## 16. Definition of done Executable on SQLite and PostgreSQL; ACs pass incl. concurrency + raw-bypass; bounded PR; no self-review/merge. ## 17. Known limitations / deferred Class **splitting** is unsupported (merges permanent). Reversing a wrong same-decision requires operator-level re-provisioning of the principals — out of scope; note as a follow-up if needed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#824