Skip to content

fix: hide unpublished GenesisRAG17 entities from legacy reads - #18

Merged
Freshair129 merged 3 commits into
mainfrom
fix/pipeline-publication-visibility
Sep 27, 2026
Merged

Freshair129 merged 3 commits into
mainfrom
fix/pipeline-publication-visibility

Conversation

@Freshair129

@Freshair129 Freshair129 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

ADR-GKS-PIPELINE-VISIBILITY was accepted by the owner on 2026-09-27 (0.2.0). This PR changes what four frozen C0 legacy read tools return, as that ADR authorizes.

Summary

GenesisRAG17 writes its canonical entities into entities at submit, before Stage 17 has gated anything. As a result, entities from PENDING, REJECTED and FAILED_STAGE runs were:

  • returned by gks_search, gks_entity_get, gks_relations_get and gks_artifact_link;
  • reachable by the legacy resolver (a MATCHED result, or a resolveTo existence probe).

The gap analysis found this and it was deferred from #17. This PR is the ADR-first redo that the architecture review asked for.

Rule (D1): a pipeline-origin entity is visible to legacy reads only after a run that mentions it is PUBLISHED. Publication is one-way.

  • Origin is owned by GKS (D2).
    • Migration 0007 adds entities.origin. Only the pipeline submit writer sets 'pipeline', so no request field, metadata key or norm key can set it.
    • The backfill marks a row 'pipeline' only if a run recorded it and the legacy path never created it (no CREATED mention).
    • It also adds an entity_id-leading index for the visibility check.
  • One rule applied everywhere, in SQL:
    • search, getEntity (and through it relations_get and artifact_link), getRelations (D5), the legacy resolution pool (D3, which also covers resolveTo) and D9 BIND/MERGE operands (D4).
    • Stage 9 pipeline reuse opts in with includeUnpublishedPipeline: true, so repeated runs still converge on one identity.
  • Hidden looks the same as absent.
    • A hidden ref returns the same response as a missing one, for every tenant.
    • A legacy norm key can imitate a typed pipeline key (norm_v1 keeps U+0000 and caseless types). When that happens the legacy entity is created under the existing D2 discriminator, rather than a gks_conflict that would reveal the hidden row.
  • Nothing is deleted or rewritten, and no response shape changes. The ADR has a table of observable changes.

Requirements addressed from the SRS blueprint: GKS-GOV-002 and the legacy-read half of GKS-RET-002.

Known limits (recorded in the ADR)

  • Pipeline Stage 9 reuse does not follow supersession, and this predates the PR. D4 now enforces that a repair MERGE keeps the pipeline entity as the survivor: superseding a pipeline-origin entity is refused with gks_conflict.
  • The rule is enforced on reads and resolution. The remaining write paths that look entities up without the predicate only ever get refs from the visible pool or refs GKS computes itself.
  • Main now includes the schema-ahead guard from fix: close P0 gaps from the SRS blueprint gap analysis #17, so rolling back to an artifact from before 0007 is refused (GKS_SCHEMA_AHEAD). Roll back by restoring the pre-migration backup.

Test plan

  • npm test after merging fix: close P0 gaps from the SRS blueprint gap analysis #17 into this branch: vitest 237 passed, 2 skipped (MSP integration suites need MSP_REPO_ROOT); security 12/12
  • Contract tests (in pipeline-genesisrag17.test.mjs):
    • hidden while PENDING / REJECTED / FAILED_STAGE, and visible after publication;
    • a rejected run's entity is revealed by a later published run that reuses it;
    • legacy promote neither matches nor resolveTo-probes a hidden entity;
    • D9 BIND/MERGE are refused as "does not resolve";
    • relations with a hidden endpoint are omitted;
    • a legacy entity with metadata.pipelineVersion stays visible;
    • a norm-key imitation is created rather than refused;
    • the backfill is exercised by rewinding and reapplying 0007, including a legacy entity that pipeline reuse has claimed.
  • Security test: for both the owning tenant and a foreign tenant, an unpublished entity is indistinguishable from an absent one (entity_get, search, relations_get, artifact_link, resolveTo), and the legacy pool excludes it.
  • Mutation checks: removing the visibility predicate fails 6 tests; removing the discriminator branch fails the collision test; removing the backfill CREATED clause fails the backfill test.
  • RKOI architecture review, first pass: REVISION_NEEDED. Every finding (norm-key collision oracle, backfill-clause coverage, merge-survivor guidance, write-path note, pre-upgrade refs, FAILED_STAGE / resolveTo tests) is addressed in this commit.
  • RKOI re-review: APPROVED on architecture, with no critical findings. Both of its non-blocking follow-ups are now done:
    • the merge-survivor rule is enforced in code (superseding a pipeline-origin entity is refused);
    • D3 now has the sentence on the two-candidate (AMBIGUOUS) match that occurs after publication for an imitation string.
  • Owner approval of ADR-GKS-PIPELINE-VISIBILITY (accepted 2026-09-27)
  • Merge-survivor rule enforced in code: a new contract test covers refusing a pipeline loser and accepting a pipeline survivor, and the mutation check fails without the guard. Local suite after this commit: vitest 232 passed, 2 skipped; security 12/12.

🤖 Generated with Claude Code

Freshair129 and others added 2 commits September 27, 2026 09:51
Proposed in ADR-GKS-PIPELINE-VISIBILITY (awaiting owner approval).

- Migration 0007 adds a GKS-owned entities.origin column. Only the pipeline
  submit writer sets 'pipeline'. The backfill marks a row pipeline-origin only
  when a run recorded it and the legacy path never created it, and adds an
  entity_id-leading index on pipeline_mentions.
- search, getEntity (and so relations_get and artifact_link), getRelations,
  the legacy resolution pool (so resolveTo too) and D9 BIND/MERGE operands
  hide pipeline entities until a mentioning run is PUBLISHED. Stage 9 reuse
  opts in with includeUnpublishedPipeline.
- A legacy norm key that imitates a hidden typed pipeline key is created under
  the D2 discriminator instead of surfacing gks_conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The owner approved ADR-GKS-PIPELINE-VISIBILITY (0.2.0, accepted
  2026-09-27).
- D4 is now enforced in code: a D9 MERGE whose supersededRef is a
  pipeline-origin entity is refused with gks_conflict, because Stage 9 reuse
  finds pipeline entities by deterministic id and does not follow
  supersession. A pipeline entity can still be the survivor. Covered by a
  test and mutation-checked.
- D3 notes that after publication an imitation string can resolve AMBIGUOUS.
- Revision rows in the data model, port contract, C0 qualification and
  GenesisRAG17 ADRs now reference the accepted decision.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Freshair129 Freshair129 changed the title fix: hide unpublished GenesisRAG17 entities from legacy reads (ADR proposed) fix: hide unpublished GenesisRAG17 entities from legacy reads Sep 27, 2026
…ion-visibility

# Conflicts:
#	docs/ADR-GKS-GENESISRAG17.md
@Freshair129
Freshair129 merged commit bb00cef into main Sep 27, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant