Skip to content

Cairnet bridge principal binding — canonical value is `agent:petrova-cairnet-bridge`


title: Cairnet bridge principal binding — canonical value is agent:petrova-cairnet-bridge date: 2026-05-18 status: accepted outranks: [] mr_compliance: [MR-4, MR-7] relates_to:

  • docs/findings/2026-05-18-sp1-5-agent-prefix-seam-defect.md
  • docs/findings/2026-05-17-sp1-seam-defect.md
  • docs/plans/2026-05-17-sp1.5-seam-remediation-implementation.md
  • docs/specs/2026-05-17-sp1.5-seam-remediation-design.md

Cairnet bridge principal binding — canonical value is agent:petrova-cairnet-bridge

Section titled “Cairnet bridge principal binding — canonical value is agent:petrova-cairnet-bridge”

The ROCKY cairnet seam requires four surfaces to agree on ONE identity for the wire-time governance stone: airlock (bridge OAuth client) → Pebble (auth + stone record) → petrova-codes (rocky probe query) → eva-hq (operator prompt / evidence block). SP-1.5 remediated the SP-1 seam-defect; during it the binding contract was reconciled twice.

  1. Plan-as-written assumed petrova-cairnet-bridge-001 (a per-repo <slug>-bridge-001 form) carried via airlock client metadata. Superseded — see step 2.
  2. 2026-05-18, reconciliation 1 (plan owner): airlock only projects metadata.customClaims onto tokens, and Pebble (R1, faithful KAHN port) derives the principal from the introspection sub/client_id for client_credentials tokens — never a custom claim. So the principal is the OAuth client_id petrova-cairnet-bridge (no -001). The airlock client metadata was reverted to {} (R2 net change = only the cairn:read scope add). The collection-owner id <slug>-<role>-001 is a SEPARATE identity (agent registration / lore-collection ownership), never the probe query key — R5 split the conflated <<CAIRNET_AGENT_ID>> placeholder into owner vs <<CAIRNET_PRODUCER_PRINCIPAL>>.
  3. 2026-05-18, reconciliation 2 (terminal gate + plan owner, Option A): the SP-1.5 terminal whole-seam gate found Pebble’s _principal_triple (cairn.py:148-154) records machine-agent stones as f"agent:{binding}". The stone is therefore recorded under agent:petrova-cairnet-bridge; the bare form matches zero stones. CR1 proved this empirically (real auth + cairn POST + Postgres). Plan owner chose the probe/prompt-side correction (no Pebble doctrine change). Canonical binding value: agent:petrova-cairnet-bridge.
  • The rocky evidence block cairnet_agent_id, the rocky probe ?agent= query (URL-encoded to ?agent=agent%3Apetrova-cairnet-bridge, Pebble decodes it server-side), and the eva-hq prompt’s <<CAIRNET_PRODUCER_PRINCIPAL>> all resolve to agent:petrova-cairnet-bridge.
  • No new Pebble or petrova-codes source code: the probe passes ev.cairnet_agent_id through verbatim; R1’s KAHN-faithful auth is unchanged. The change is the documented/contract VALUE only.
  • A cross-repo POST→GET-by-?agent= test now exists in pebble (tests/integration/test_cairn_bridge_principal_seam.py) and a petrova-codes contract-pin test (cli/tests/probes/cairnet-binding-contract.test.ts) locks the prefixed literal + %3A encoding. Their absence was the structural root cause that let the original defect pass 18 + 5 green tasks.
  • The cairnet_agent_id field name now carries an agent:-prefixed value (a documented naming wart; the field is named for the recorded producer principal).
  • Pebble’s agent:/human: identity-provenance doctrine is unchanged (Option A deliberately did not touch it).

Accepted. Terminal whole-seam gate round 2 = GREEN; SC-1 delivered end-to-end. Two doc-correctness residuals tracked as next-round input in docs/findings/2026-05-18-sp1-5-agent-prefix-seam-defect.md (MR-2 — not bolted onto the GREEN round).