@agenticprimitives/ontology 1.0.0-alpha.46 → 1.0.0-alpha.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/cbox/controlled-vocabularies.ttl +10 -6
  2. package/cbox/interaction-shapes.shacl.ttl +22 -5
  3. package/cbox/naming-registry-shapes.shacl.ttl +38 -6
  4. package/cbox/run-provenance-shapes.shacl.ttl +10 -4
  5. package/cbox/value-rail-shapes.shacl.ttl +60 -0
  6. package/dist/artifacts.d.ts +2 -2
  7. package/dist/artifacts.d.ts.map +1 -1
  8. package/dist/artifacts.js +19 -0
  9. package/dist/artifacts.js.map +1 -1
  10. package/dist/household.d.ts.map +1 -1
  11. package/dist/household.js +7 -3
  12. package/dist/household.js.map +1 -1
  13. package/dist/index.d.ts +13 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +13 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/party-roles.d.ts.map +1 -1
  18. package/dist/party-roles.js +6 -3
  19. package/dist/party-roles.js.map +1 -1
  20. package/dist/stewardship.d.ts +34 -0
  21. package/dist/stewardship.d.ts.map +1 -0
  22. package/dist/stewardship.js +38 -0
  23. package/dist/stewardship.js.map +1 -0
  24. package/dist/transitions.d.ts +10 -1
  25. package/dist/transitions.d.ts.map +1 -1
  26. package/dist/transitions.js +12 -2
  27. package/dist/transitions.js.map +1 -1
  28. package/dist/vault-records.d.ts +33 -5
  29. package/dist/vault-records.d.ts.map +1 -1
  30. package/dist/vault-records.js +122 -96
  31. package/dist/vault-records.js.map +1 -1
  32. package/dist/versions.generated.d.ts +34 -34
  33. package/dist/versions.generated.js +33 -33
  34. package/dist/versions.generated.js.map +1 -1
  35. package/package.json +3 -3
  36. package/tbox/actor-context.ttl +1 -0
  37. package/tbox/content.ttl +5 -0
  38. package/tbox/core.ttl +34 -4
  39. package/tbox/estate.ttl +7 -1
  40. package/tbox/geo.ttl +6 -0
  41. package/tbox/household.ttl +5 -3
  42. package/tbox/identity.ttl +12 -1
  43. package/tbox/inference.ttl +7 -2
  44. package/tbox/naming.ttl +2 -2
  45. package/tbox/payload.ttl +35 -31
  46. package/tbox/payment.ttl +10 -6
  47. package/tbox/privacy-credential.ttl +21 -1
  48. package/tbox/skills.ttl +5 -0
  49. package/tbox/transition.ttl +60 -3
  50. package/tbox/values.ttl +2 -1
  51. package/versions.adoption.json +18 -0
@@ -47,6 +47,9 @@ const PPLAN = 'http://purl.org/net/p-plan#';
47
47
  const EPPLAN = 'https://w3id.org/ep-plan#';
48
48
  const APEVAL = 'https://agenticprimitives.dev/ns/evaluation#';
49
49
  const DQV = 'http://www.w3.org/ns/dqv#';
50
+ export const VAULT_RECORD_ROLES = ['entity', 'index', 'secret'];
51
+ /** What a `secret` row IS, in the T-box — bound by IRI so the role is not vocabulary this file invented. */
52
+ export const HELD_SECRET_CLASS = 'https://agenticprimitives.dev/ns/core#HeldSecret';
50
53
  /**
51
54
  * The record kinds this substrate stores, each bound to what it IS.
52
55
  *
@@ -63,14 +66,14 @@ export const VAULT_RECORD_BINDINGS = [
63
66
  // it was here until the check started reading record bindings. You ask about endeavors; the log is how
64
67
  // one of them got where it is.
65
68
  { match: { prefix: 'coordination.endeavor:events:' }, class: `${APCOORD}Endeavor`, label: 'endeavor history', plural: 'endeavor history', ownedBy: 'either', role: 'index' },
66
- { match: { prefix: 'coordination.endeavor:' }, class: `${APCOORD}Endeavor`, label: 'endeavor', plural: 'endeavors', ownedBy: 'either' },
67
- { match: { exact: 'coordination.requests' }, class: `${APCOORD}EndeavorRequest`, label: 'request for work', plural: 'requests for work', ownedBy: 'either' },
69
+ { match: { prefix: 'coordination.endeavor:' }, class: `${APCOORD}Endeavor`, label: 'endeavor', plural: 'endeavors', ownedBy: 'either', role: 'entity' },
70
+ { match: { exact: 'coordination.requests' }, class: `${APCOORD}EndeavorRequest`, label: 'request for work', plural: 'requests for work', ownedBy: 'either', role: 'entity' },
68
71
  // ── The parties' own evidence of a transfer (spec 360) ────────────────────────────────────────
69
72
  // A payment's StepReceipt is AUTHORITY evidence and lives in the audit sink. This is the different
70
73
  // artifact the two PARTIES hold: what Alice can point at to say she paid, and what tells Bob he was
71
74
  // paid, to which treasury, in what amount. Keyed by the transaction, because that is the one identifier
72
75
  // both sides can check against the chain rather than take on trust.
73
- { match: { prefix: 'payment.receipt:' }, class: `${APIX}PaymentReceipt`, label: 'payment receipt', plural: 'payment receipts', ownedBy: 'either',
76
+ { match: { prefix: 'payment.receipt:' }, class: `${APIX}PaymentReceipt`, label: 'payment receipt', plural: 'payment receipts', ownedBy: 'either', role: 'entity',
74
77
  properties: {
75
78
  payer: `${APIX}receiptPayer`,
76
79
  payee: `${APIX}receiptPayee`,
@@ -82,13 +85,13 @@ export const VAULT_RECORD_BINDINGS = [
82
85
  // ── Organization membership (spec 324, ADR-0025) ──────────────────────────────────────────────
83
86
  // The ROSTER an organization keeps of its own members. This is the record `organization.membership.list`
84
87
  // reads today through its own hand-written invoker — W4 retires that in favour of this binding.
85
- { match: { exact: 'directory.data' }, class: `${APORG}DirectoryListing`, label: 'member listing', plural: 'member listings', ownedBy: 'organization' },
86
- { match: { prefix: 'org.invite:agent:' }, class: `${APORG}MembershipInvitation`, label: 'membership invitation', plural: 'membership invitations', ownedBy: 'organization' },
88
+ { match: { exact: 'directory.data' }, class: `${APORG}DirectoryListing`, label: 'member listing', plural: 'member listings', ownedBy: 'organization', role: 'entity' },
89
+ { match: { prefix: 'org.invite:agent:' }, class: `${APORG}MembershipInvitation`, label: 'membership invitation', plural: 'membership invitations', ownedBy: 'organization', role: 'entity' },
87
90
  // Spec 401 (amended 2026-10-26) — ONE HALF of a friendship: a person's own offer to another person (`friend:<their sa>`),
88
91
  // with the grant they signed. A friendship is never a record — it is derived from two of these, one in each vault.
89
- { match: { prefix: 'friend:' }, class: `${APORG}FriendshipOffer`, label: 'friendship offer', plural: 'friendship offers', ownedBy: 'person',
92
+ { match: { prefix: 'friend:' }, class: `${APORG}FriendshipOffer`, label: 'friendship offer', plural: 'friendship offers', ownedBy: 'person', role: 'entity',
90
93
  properties: { offeredTo: `${APORG}offeredTo`, friendType: `${APORG}friendTypeLabel`, delegation: `${APORG}offerGrant`, status: `${APORG}offerStatus`, withdrawnAt: `${APORG}offerWithdrawnAt` } },
91
- { match: { exact: 'org.applications' }, class: `${APORG}MembershipApplication`, label: 'membership application', plural: 'membership applications', ownedBy: 'organization' },
94
+ { match: { exact: 'org.applications' }, class: `${APORG}MembershipApplication`, label: 'membership application', plural: 'membership applications', ownedBy: 'organization', role: 'entity' },
92
95
  // THE MEMBERSHIP ITSELF — spec 325's shape, in the organization's own vault. Distinct from the
93
96
  // invitation, which the T-box files under "Enrollment instruments (NOT membership)": an invitation is
94
97
  // how somebody came to be admitted, and satisfying one creates nothing. The membership is the record
@@ -98,7 +101,7 @@ export const VAULT_RECORD_BINDINGS = [
98
101
  // already carries, and clear of `org.membership:local-names`, which is a name map and not a member.
99
102
  {
100
103
  match: { prefix: 'org.membership:member:' }, class: `${APORG}OrganizationMembership`,
101
- label: 'member', plural: 'members', ownedBy: 'organization',
104
+ label: 'member', plural: 'members', ownedBy: 'organization', role: 'entity',
102
105
  // Spec 325's shape, field for field — this is what "readable by the ontology" looks like in practice.
103
106
  properties: {
104
107
  memberAgent: `${APORG}memberAgent`,
@@ -124,7 +127,7 @@ export const VAULT_RECORD_BINDINGS = [
124
127
  // Ask that can change a name can change a street address, and the record's write allow-list agrees.
125
128
  {
126
129
  match: { exact: 'impact-profile' }, class: `${APCON}ContactProfile`,
127
- label: 'contact profile', plural: 'contact profiles', ownedBy: 'person',
130
+ label: 'contact profile', plural: 'contact profiles', ownedBy: 'person', role: 'entity',
128
131
  properties: { ...CONTACT_PROFILE_PROPERTIES, 'contact.location.precision': `${APCON}locationPrecision` },
129
132
  },
130
133
  // A PERSON's own record of who they are connected to — private, a vault credential and never an
@@ -135,14 +138,14 @@ export const VAULT_RECORD_BINDINGS = [
135
138
  // per person holding their own household — not a shared roster, because two people's records can
136
139
  // disagree and the honest model says whose you are reading.
137
140
  match: { exact: 'household.data' }, class: `${APHH}Household`,
138
- label: 'household', plural: 'household', ownedBy: 'person',
141
+ label: 'household', plural: 'household', ownedBy: 'person', role: 'entity',
139
142
  properties: {
140
143
  'members[].agent': `${APHH}householdMember`,
141
144
  'members[].role': `${APHH}householdRole`,
142
145
  'members[].kin': `${APHH}kinRelation`,
143
146
  },
144
147
  },
145
- { match: { exact: 'relationships.data' }, class: `${APORG}OrganizationMembership`, label: 'organization you belong to', plural: 'organizations you belong to', ownedBy: 'person',
148
+ { match: { exact: 'relationships.data' }, class: `${APORG}OrganizationMembership`, label: 'organization you belong to', plural: 'organizations you belong to', ownedBy: 'person', role: 'entity',
146
149
  // The map is KEYED by the organization — the thing a reader most often gets wrong here.
147
150
  properties: {
148
151
  'orgs{}': `${APORG}organizationAgent`,
@@ -151,7 +154,7 @@ export const VAULT_RECORD_BINDINGS = [
151
154
  },
152
155
  },
153
156
  // ── Content (spec 347 / the field artifacts) ──────────────────────────────────────────────────
154
- { match: { prefix: 'content.artifact.' }, class: `${APFUL}Artifact`, label: 'artifact', plural: 'artifacts', ownedBy: 'either',
157
+ { match: { prefix: 'content.artifact.' }, class: `${APFUL}Artifact`, label: 'artifact', plural: 'artifacts', ownedBy: 'either', role: 'entity',
155
158
  properties: {
156
159
  'kind': `${APFUL}artifactKind`,
157
160
  'commitment': `${APFUL}bodyHash`,
@@ -159,49 +162,49 @@ export const VAULT_RECORD_BINDINGS = [
159
162
  },
160
163
  // ── Conversation (spec 313/316) ───────────────────────────────────────────────────────────────
161
164
  // A message BODY is the content of one message; a topic is the conversation it sits in.
162
- { match: { prefix: 'message.body:' }, class: `${APFUL}Message`, label: 'message', plural: 'messages', ownedBy: 'either' },
163
- { match: { prefix: 'conversation.topic:' }, class: `${APMSG}DiscussionTopic`, label: 'discussion', plural: 'discussions', ownedBy: 'either' },
165
+ { match: { prefix: 'message.body:' }, class: `${APFUL}Message`, label: 'message', plural: 'messages', ownedBy: 'either', role: 'entity' },
166
+ { match: { prefix: 'conversation.topic:' }, class: `${APMSG}DiscussionTopic`, label: 'discussion', plural: 'discussions', ownedBy: 'either', role: 'entity' },
164
167
  // ── Relationship credentials (spec 410 §8) ───────────────────────────────────────────────────
165
168
  // The countersigned form of a relationship, one copy in each party's vault; the revocation likewise.
166
- { match: { prefix: 'relationships.credential:' }, class: `${AP}RelationshipCredential`, label: 'relationship credential', plural: 'relationship credentials', ownedBy: 'either',
169
+ { match: { prefix: 'relationships.credential:' }, class: `${AP}RelationshipCredential`, label: 'relationship credential', plural: 'relationship credentials', ownedBy: 'either', role: 'entity',
167
170
  properties: { kind: `${AP}relationshipKind` },
168
171
  },
169
- { match: { prefix: 'relationships.revocation:' }, class: `${AP}RelationshipCredential`, label: 'relationship revocation', plural: 'relationship revocations', ownedBy: 'either',
172
+ { match: { prefix: 'relationships.revocation:' }, class: `${AP}RelationshipCredential`, label: 'relationship revocation', plural: 'relationship revocations', ownedBy: 'either', role: 'entity',
170
173
  properties: { credential: `${AP}revokes` },
171
174
  },
172
175
  // ── Governance of the common model (spec 410 §10) ────────────────────────────────────────────
173
- { match: { prefix: 'ontology.meaning:' }, class: `${APGOV}LocalMeaning`, label: 'local meaning of a common term', plural: 'local meanings', ownedBy: 'organization',
176
+ { match: { prefix: 'ontology.meaning:' }, class: `${APGOV}LocalMeaning`, label: 'local meaning of a common term', plural: 'local meanings', ownedBy: 'organization', role: 'entity',
174
177
  properties: { term: `${APGOV}ofTerm`, organization: `${APGOV}heldBy`, relation: `${APGOV}mappingRelation` },
175
178
  },
176
- { match: { exact: 'ontology.adopted' }, class: `${APGOV}AdoptedVersion`, label: 'adopted ontology version', plural: 'adopted ontology versions', ownedBy: 'either',
179
+ { match: { exact: 'ontology.adopted' }, class: `${APGOV}AdoptedVersion`, label: 'adopted ontology version', plural: 'adopted ontology versions', ownedBy: 'either', role: 'entity',
177
180
  properties: { manifestDigest: `${APGOV}manifestDigest`, adoptedAt: `${APGOV}adoptedAt`, proposalRef: `${APGOV}proposalRef` },
178
181
  },
179
- { match: { prefix: 'ontology.steward:' }, class: `${APGOV}Steward`, label: 'steward of a term', plural: 'stewards', ownedBy: 'either',
182
+ { match: { prefix: 'ontology.steward:' }, class: `${APGOV}Steward`, label: 'steward of a term', plural: 'stewards', ownedBy: 'either', role: 'entity',
180
183
  properties: { subject: `${APGOV}stewards`, stewardAgent: `${APGOV}stewardAgent`, charterRef: `${APGOV}charterRef` },
181
184
  },
182
185
  // ── Delegation lineage (spec 410 §1.2) ───────────────────────────────────────────────────────
183
186
  // A key-signed wire re-issued for a credential rotation, and which wire it replaces. The delegator's vault holds
184
187
  // it; the delegate fetches the head of the lineage from the delegator's agent. Never a grant of anything new.
185
- { match: { prefix: 'delegation.lineage:' }, class: `${APDEL}Delegation`, label: 'delegation re-issued for a rotation', plural: 'delegations re-issued for a rotation', ownedBy: 'either',
188
+ { match: { prefix: 'delegation.lineage:' }, class: `${APDEL}Delegation`, label: 'delegation re-issued for a rotation', plural: 'delegations re-issued for a rotation', ownedBy: 'either', role: 'entity',
186
189
  properties: { supersedes: `${APDEL}supersedes` },
187
190
  },
188
191
  // ── Resolution (spec 338) ─────────────────────────────────────────────────────────────────────
189
- { match: { exact: 'resolution.grants' }, class: `${APAR}PrivateResolutionGrant`, label: 'way to reach someone', plural: 'ways to reach people', ownedBy: 'either',
192
+ { match: { exact: 'resolution.grants' }, class: `${APAR}PrivateResolutionGrant`, label: 'way to reach someone', plural: 'ways to reach people', ownedBy: 'either', role: 'entity',
190
193
  // The held record names WHOSE agent it opens; the address itself comes from the resolver, per use.
191
194
  properties: {
192
195
  'grants[].owner': `${APAR}permitsDiscoveryOf`,
193
196
  },
194
197
  },
195
- { match: { exact: 'resolution.requests' }, class: `${APAR}AgentConnectionInvitation`, label: 'request for a way to reach an agent', plural: 'requests for a way to reach an agent', ownedBy: 'either' },
198
+ { match: { exact: 'resolution.requests' }, class: `${APAR}AgentConnectionInvitation`, label: 'request for a way to reach an agent', plural: 'requests for a way to reach an agent', ownedBy: 'either', role: 'entity' },
196
199
  // ── What an agent IS and CAN DO ───────────────────────────────────────────────────────────────
197
- { match: { exact: 'capabilities.data' }, class: `${APS}CapabilityCatalog`, label: 'capability', plural: 'capabilities', ownedBy: 'either',
200
+ { match: { exact: 'capabilities.data' }, class: `${APS}CapabilityCatalog`, label: 'capability', plural: 'capabilities', ownedBy: 'either', role: 'entity',
198
201
  // The record is the catalogue; each ENTRY is a claim, so its fields map to SkillClaim's properties.
199
202
  properties: {
200
203
  '[].relation': `${APS}claimRelation`,
201
204
  '[].label': `${APS}semanticType`,
202
205
  },
203
206
  },
204
- { match: { exact: 'skills.data' }, class: `${APS}SkillClaim`, label: 'skill claim', plural: 'skill claims', ownedBy: 'either',
207
+ { match: { exact: 'skills.data' }, class: `${APS}SkillClaim`, label: 'skill claim', plural: 'skill claims', ownedBy: 'either', role: 'entity',
205
208
  properties: {
206
209
  '[].definitionId': `${APS}definitionId`,
207
210
  '[].subject': `${APS}claimSubject`,
@@ -217,7 +220,7 @@ export const VAULT_RECORD_BINDINGS = [
217
220
  properties: { '[].kind': `${APCR}credentialKind` } },
218
221
  // The emails and phones that open this home and are told when something changes. Never a signer.
219
222
  { match: { exact: 'security.channels' }, class: `${APCR}ChannelFacet`, label: 'contact channel', plural: 'contact channels', ownedBy: 'person', role: 'index' },
220
- { match: { exact: 'impact-profile' }, class: `${APROF}AgentProfile`, label: 'profile', plural: 'profile', ownedBy: 'either',
223
+ { match: { exact: 'impact-profile' }, class: `${APROF}AgentProfile`, label: 'profile', plural: 'profile', ownedBy: 'either', role: 'entity',
221
224
  // Observed records carry only `contact`, which the T-box has no property for — see the coverage ledger.
222
225
  properties: {
223
226
  'displayName': `${APROF}displayName`,
@@ -227,11 +230,11 @@ export const VAULT_RECORD_BINDINGS = [
227
230
  // An index over the artifacts, not a thing beside them.
228
231
  { match: { exact: 'content.catalog' }, class: `${APFUL}Artifact`, label: 'content index', plural: 'content index', ownedBy: 'either', role: 'index' },
229
232
  // ── The card studio (spec 347) ────────────────────────────────────────────────────────────────
230
- { match: { prefix: 'agent-cards:' }, class: `${AP}A2AAgentCard`, label: 'agent card', plural: 'agent cards', ownedBy: 'either' },
233
+ { match: { prefix: 'agent-cards:' }, class: `${AP}A2AAgentCard`, label: 'agent card', plural: 'agent cards', ownedBy: 'either', role: 'entity' },
231
234
  // ── The playbook an agent runs under (spec 354) ───────────────────────────────────────────────
232
235
  {
233
236
  match: { exact: 'archetype.assignment' }, class: `${APS}ArchetypeAssignment`,
234
- label: 'playbook', plural: 'playbook', ownedBy: 'either',
237
+ label: 'playbook', plural: 'playbook', ownedBy: 'either', role: 'entity',
235
238
  properties: {
236
239
  archetypeId: `${APS}assignedArchetype`,
237
240
  definitionDigest: `${APS}definitionDigest`,
@@ -246,7 +249,7 @@ export const VAULT_RECORD_BINDINGS = [
246
249
  // the same IRI the context maps it to — bound twice on purpose, checked once by the build.
247
250
  {
248
251
  match: { prefix: 'run.provenance:' }, class: `${EPPLAN}ExecutionTraceBundle`,
249
- label: 'run provenance', plural: 'run provenances', ownedBy: 'either',
252
+ label: 'run provenance', plural: 'run provenances', ownedBy: 'either', role: 'entity',
250
253
  properties: {
251
254
  wasAttributedTo: `${PROV}wasAttributedTo`,
252
255
  wasInformedBy: `${PROV}wasInformedBy`,
@@ -338,7 +341,7 @@ export const VAULT_RECORD_BINDINGS = [
338
341
  // estate it was (`estate`). A claim about where to look — the holder recomputes the digest and reads the registry.
339
342
  {
340
343
  match: { prefix: 'run.anchor:' }, class: `${APEXEC}ReceiptAnchor`,
341
- label: 'run anchor', plural: 'run anchors', ownedBy: 'either',
344
+ label: 'run anchor', plural: 'run anchors', ownedBy: 'either', role: 'entity',
342
345
  properties: {
343
346
  digest: `${APEXEC}anchorDigest`,
344
347
  registry: `${APEXEC}anchorRegistry`,
@@ -352,7 +355,7 @@ export const VAULT_RECORD_BINDINGS = [
352
355
  // metric (and per step where the number is a step's). Descriptive, never judged; no words (shape M3).
353
356
  {
354
357
  match: { prefix: 'run.measures:' }, class: `${APEVAL}RunMeasures`,
355
- label: 'run measurements', plural: 'run measurements', ownedBy: 'either',
358
+ label: 'run measurements', plural: 'run measurements', ownedBy: 'either', role: 'entity',
356
359
  properties: {
357
360
  wasDerivedFrom: `${PROV}wasDerivedFrom`,
358
361
  wasAttributedTo: `${PROV}wasAttributedTo`,
@@ -376,7 +379,7 @@ export const VAULT_RECORD_BINDINGS = [
376
379
  // (the service-agent-signing rule), or by a person's SA at her Home.
377
380
  {
378
381
  match: { prefix: 'run.assessment:' }, class: `${APEVAL}Assessment`,
379
- label: 'run assessment', plural: 'run assessments', ownedBy: 'either',
382
+ label: 'run assessment', plural: 'run assessments', ownedBy: 'either', role: 'entity',
380
383
  properties: {
381
384
  subject: `${PROV}used`,
382
385
  recordDigest: `${APEXEC}anchorDigest`,
@@ -395,7 +398,7 @@ export const VAULT_RECORD_BINDINGS = [
395
398
  // That is the whole reason this is a record and not a handoff token.
396
399
  {
397
400
  match: { prefix: 'endeavor.continuation:' }, class: `${APCOORD}Endeavor`,
398
- label: 'continuation package', plural: 'continuation packages', ownedBy: 'either',
401
+ label: 'continuation package', plural: 'continuation packages', ownedBy: 'either', role: 'entity',
399
402
  properties: {
400
403
  // The objective is the Endeavor's OutcomeSpecification — the observable success definition that already
401
404
  // exists, not a prose restatement of it. An agent picking the work up is told what "done" means in the
@@ -411,7 +414,7 @@ export const VAULT_RECORD_BINDINGS = [
411
414
  // Every exchange is one signed unit by its author; a steward's determination closes it; it reverses nothing.
412
415
  {
413
416
  match: { prefix: 'interaction.dispute:' }, class: `${APIX}Interaction`,
414
- label: 'dispute', plural: 'disputes', ownedBy: 'either',
417
+ label: 'dispute', plural: 'disputes', ownedBy: 'either', role: 'entity',
415
418
  properties: {
416
419
  profileVersion: `${APIX}profileVersion`,
417
420
  'exchanges[].performative': `${APIX}performative`,
@@ -420,7 +423,7 @@ export const VAULT_RECORD_BINDINGS = [
420
423
  // ── The run's pointer to the dispute that cites it (spec 410 §10, `apexec:disputedBy`) ──
421
424
  {
422
425
  match: { prefix: 'run.dispute:' }, class: `${APEXEC}ServiceExecution`,
423
- label: 'run dispute', plural: 'run disputes', ownedBy: 'either',
426
+ label: 'run dispute', plural: 'run disputes', ownedBy: 'either', role: 'entity',
424
427
  properties: {
425
428
  disputedBy: `${APEXEC}disputedBy`,
426
429
  },
@@ -429,7 +432,7 @@ export const VAULT_RECORD_BINDINGS = [
429
432
  // The body a resume or a person fetches under the agent's grant; the receipt's outputDigest commits to it.
430
433
  {
431
434
  match: { prefix: 'run.artifact:' }, class: `${APEXEC}RunArtifact`,
432
- label: 'run artifact', plural: 'run artifacts', ownedBy: 'either',
435
+ label: 'run artifact', plural: 'run artifacts', ownedBy: 'either', role: 'entity',
433
436
  properties: {
434
437
  digest: `${APEXEC}artifactDigest`,
435
438
  bytes: `${APEXEC}artifactBytes`,
@@ -439,7 +442,7 @@ export const VAULT_RECORD_BINDINGS = [
439
442
  // The files the model wrote and the test evidence as recorded; the PR opened from it names this record.
440
443
  {
441
444
  match: { prefix: 'build.run:' }, class: `${APEXEC}BuildArtifact`,
442
- label: 'build run', plural: 'build runs', ownedBy: 'either',
445
+ label: 'build run', plural: 'build runs', ownedBy: 'either', role: 'entity',
443
446
  properties: {
444
447
  repository: `${APEXEC}buildRepository`,
445
448
  base: `${APEXEC}buildBase`,
@@ -455,7 +458,7 @@ export const VAULT_RECORD_BINDINGS = [
455
458
  // ── Build promotions (spec 398 §9.4 / ap-build B5) — the exact tuple a steward's signature was over ──
456
459
  {
457
460
  match: { prefix: 'build.promotion:' }, class: `${APEXEC}BuildPromotion`,
458
- label: 'build promotion', plural: 'build promotions', ownedBy: 'either',
461
+ label: 'build promotion', plural: 'build promotions', ownedBy: 'either', role: 'entity',
459
462
  properties: {
460
463
  repository: `${APEXEC}buildRepository`,
461
464
  commit: `${APEXEC}promotedCommit`,
@@ -468,7 +471,7 @@ export const VAULT_RECORD_BINDINGS = [
468
471
  // ── The agent's budget (P1.4) — what it may do in a day, declared by its steward ──
469
472
  {
470
473
  match: { exact: 'agent.budget' }, class: `${APCTX}AgentBudget`,
471
- label: 'agent budget', plural: 'agent budget', ownedBy: 'either',
474
+ label: 'agent budget', plural: 'agent budget', ownedBy: 'either', role: 'entity',
472
475
  properties: { asksPerDay: `${APCTX}asksPerDay`, vaultCallsPerDay: `${APCTX}vaultCallsPerDay` },
473
476
  },
474
477
  // ── The town's model gateway (spec 434) — inference.svc's OWN records: policy, entitlements, receipts ──
@@ -476,28 +479,28 @@ export const VAULT_RECORD_BINDINGS = [
476
479
  // service's own policy over its own resource, never a delegation (G8). `assertedAgent` is what the caller SAID.
477
480
  {
478
481
  match: { prefix: 'inference.receipt:' }, class: `${APINF}InferenceReceipt`,
479
- label: 'inference receipt', plural: 'inference receipts', ownedBy: 'either',
482
+ label: 'inference receipt', plural: 'inference receipts', ownedBy: 'either', role: 'entity',
480
483
  properties: { profile: `${APINF}profileId`, profileVersion: `${APINF}profileVersion`, provider: `${APINF}modelProvider`, model: `${APINF}modelId`, principal: `${APINF}principal`, assertedAgent: `${APINF}assertedAgent`, costMicroUsd: `${APINF}costMicroUsd`, attempt: `${APINF}attempt`, fallbackOf: `${APINF}fallbackOf`, reconciliation: `${APINF}reconciliationState`, outcome: `${APINF}outcome`, purpose: `${APINF}purpose`, estate: `${APINF}estate`, clientKind: `${APINF}clientKind` },
481
484
  },
482
- { match: { prefix: 'inference.profile:' }, class: `${APINF}ModelProfile`, label: 'model profile', plural: 'model profiles', ownedBy: 'either', properties: { id: `${APINF}profileId`, 'servesCapability[]': `${APINF}servesCapability` } },
483
- { match: { prefix: 'inference.model:' }, class: `${APINF}ModelCatalogEntry`, label: 'model catalog entry', plural: 'model catalog entries', ownedBy: 'either', properties: { provider: `${APINF}modelProvider`, model: `${APINF}modelId`, enabled: `${APINF}enabled` } },
484
- { match: { prefix: 'inference.client:' }, class: `${APINF}ClientEntitlement`, label: 'inference client', plural: 'inference clients', ownedBy: 'either', properties: { principal: `${APINF}principal`, estate: `${APINF}estate`, kind: `${APINF}clientKind` } },
485
- { match: { prefix: 'inference.policy-change:' }, class: `${APINF}PolicyChange`, label: 'inference policy change', plural: 'inference policy changes', ownedBy: 'either', properties: { recordKey: `${APINF}changedRecord`, reason: `${APINF}reason` } },
485
+ { match: { prefix: 'inference.profile:' }, class: `${APINF}ModelProfile`, label: 'model profile', plural: 'model profiles', ownedBy: 'either', role: 'entity', properties: { id: `${APINF}profileId`, 'servesCapability[]': `${APINF}servesCapability` } },
486
+ { match: { prefix: 'inference.model:' }, class: `${APINF}ModelCatalogEntry`, label: 'model catalog entry', plural: 'model catalog entries', ownedBy: 'either', role: 'entity', properties: { provider: `${APINF}modelProvider`, model: `${APINF}modelId`, enabled: `${APINF}enabled` } },
487
+ { match: { prefix: 'inference.client:' }, class: `${APINF}ClientEntitlement`, label: 'inference client', plural: 'inference clients', ownedBy: 'either', role: 'entity', properties: { principal: `${APINF}principal`, estate: `${APINF}estate`, kind: `${APINF}clientKind` } },
488
+ { match: { prefix: 'inference.policy-change:' }, class: `${APINF}PolicyChange`, label: 'inference policy change', plural: 'inference policy changes', ownedBy: 'either', role: 'entity', properties: { recordKey: `${APINF}changedRecord`, reason: `${APINF}reason` } },
486
489
  // ── Spec 435 / 436 / 437 — standing, manifests, the Town Ask's records ──
487
490
  // The agent's own copy of its TownStanding VC (the chain holds the hash): read to show and renew; no gate reads it.
488
- { match: { prefix: 'town.standing:' }, class: `${APATT}TownStanding`, label: 'town standing', plural: 'town standings', ownedBy: 'either', properties: { town: `${APATT}standingTown`, estate: `${APATT}standingEstate`, steward: `${APATT}standingSteward`, validUntil: `${APATT}standingValidUntil` } },
491
+ { match: { prefix: 'town.standing:' }, class: `${APATT}TownStanding`, label: 'town standing', plural: 'town standings', ownedBy: 'either', role: 'entity', properties: { town: `${APATT}standingTown`, estate: `${APATT}standingEstate`, steward: `${APATT}standingSteward`, validUntil: `${APATT}standingValidUntil` } },
489
492
  // A service's own signed MCP tool manifest, as published; a holder pins its digest on `connector.mcp:` (spec 404).
490
- { match: { prefix: 'mcp.manifest:' }, class: `${APAR}McpToolManifest`, label: 'MCP tool manifest', plural: 'MCP tool manifests', ownedBy: 'either', properties: { 'server.url': `${APAR}manifestServerUrl` } },
491
- { match: { prefix: 'mcp.bundle:' }, class: `${APAR}McpToolBundle`, label: 'MCP tool bundle', plural: 'MCP tool bundles', ownedBy: 'either' },
493
+ { match: { prefix: 'mcp.manifest:' }, class: `${APAR}McpToolManifest`, label: 'MCP tool manifest', plural: 'MCP tool manifests', ownedBy: 'either', role: 'entity', properties: { 'server.url': `${APAR}manifestServerUrl` } },
494
+ { match: { prefix: 'mcp.bundle:' }, class: `${APAR}McpToolBundle`, label: 'MCP tool bundle', plural: 'MCP tool bundles', ownedBy: 'either', role: 'entity' },
492
495
  // The Town Ask (spec 436 §5.5, 437): the context agents' memory of the Pulse — counts, never a person.
493
- { match: { prefix: 'pulse.day:' }, class: `${APINF}TownPulse`, label: "day's pulse", plural: 'daily pulses', ownedBy: 'either', properties: { day: `${APINF}pulseDay` } },
494
- { match: { prefix: 'pulse.sample:' }, class: `${APINF}TownPulse`, label: 'pulse sample', plural: 'pulse samples', ownedBy: 'either' },
495
- { match: { prefix: 'estate.checklist:' }, class: `${APINF}StandingChecklist`, label: 'standing checklist', plural: 'standing checklists', ownedBy: 'either' },
496
- { match: { prefix: 'estate.manifest:' }, class: `${APINF}EstateManifest`, label: 'estate manifest', plural: 'estate manifests', ownedBy: 'either' },
496
+ { match: { prefix: 'pulse.day:' }, class: `${APINF}TownPulse`, label: "day's pulse", plural: 'daily pulses', ownedBy: 'either', role: 'entity', properties: { day: `${APINF}pulseDay` } },
497
+ { match: { prefix: 'pulse.sample:' }, class: `${APINF}TownPulse`, label: 'pulse sample', plural: 'pulse samples', ownedBy: 'either', role: 'entity' },
498
+ { match: { prefix: 'estate.checklist:' }, class: `${APINF}StandingChecklist`, label: 'standing checklist', plural: 'standing checklists', ownedBy: 'either', role: 'entity' },
499
+ { match: { prefix: 'estate.manifest:' }, class: `${APINF}EstateManifest`, label: 'estate manifest', plural: 'estate manifests', ownedBy: 'either', role: 'entity' },
497
500
  // ── External MCP servers as connectors (spec 404) — the holder's own; the token is NOT in the record ──
498
501
  {
499
502
  match: { prefix: 'connector.mcp:' }, class: `${APCTX}McpConnector`,
500
- label: 'MCP connector', plural: 'MCP connectors', ownedBy: 'either',
503
+ label: 'MCP connector', plural: 'MCP connectors', ownedBy: 'either', role: 'entity',
501
504
  properties: {
502
505
  name: `${APCTX}connectorName`,
503
506
  url: `${APCTX}connectorUrl`,
@@ -509,7 +512,7 @@ export const VAULT_RECORD_BINDINGS = [
509
512
  // ── Conversation memory (spec 370 P7) — what the agent RESOLVED for the owner lately, in their vault ──
510
513
  {
511
514
  match: { exact: 'conversation.recent' }, class: `${APCTX}ConversationMemory`,
512
- label: 'recent conversation', plural: 'recent conversations', ownedBy: 'person',
515
+ label: 'recent conversation', plural: 'recent conversations', ownedBy: 'person', role: 'entity',
513
516
  properties: {
514
517
  'turns[].at': `${APCTX}recalledAt`,
515
518
  'turns[].parties[].agent': `${APCTX}recalledParty`,
@@ -519,7 +522,7 @@ export const VAULT_RECORD_BINDINGS = [
519
522
  // ── Learned memory (spec 358 W5) — what the owner TOLD the agent, in their own vault ────────────
520
523
  {
521
524
  match: { prefix: 'preference:' }, class: `${APCTX}LearnedPreference`,
522
- label: 'thing you told me', plural: 'things you told me', ownedBy: 'person',
525
+ label: 'thing you told me', plural: 'things you told me', ownedBy: 'person', role: 'entity',
523
526
  properties: {
524
527
  subject: `${APCTX}preferenceSubject`,
525
528
  trigger: `${APCTX}preferenceTrigger`,
@@ -529,7 +532,7 @@ export const VAULT_RECORD_BINDINGS = [
529
532
  // ── Confirmation memory (spec 385; bound here by spec 394) — which "David" the owner chose, per scope ──
530
533
  {
531
534
  match: { exact: 'confirmation.preferences' }, class: `${APCTX}ConfirmationMemory`,
532
- label: 'remembered choice', plural: 'remembered choices', ownedBy: 'person',
535
+ label: 'remembered choice', plural: 'remembered choices', ownedBy: 'person', role: 'entity',
533
536
  properties: {
534
537
  'entries[].agent': `${APCTX}confirmedParty`,
535
538
  'entries[].word': `${APCTX}confirmedWords`,
@@ -539,7 +542,7 @@ export const VAULT_RECORD_BINDINGS = [
539
542
  // ── Playbook memory — the agent's own counts on the subjects of one skill family ───────────────
540
543
  {
541
544
  match: { prefix: 'playbook.memory:' }, class: `${APCTX}PlaybookMemory`,
542
- label: 'playbook memory', plural: 'playbook memories', ownedBy: 'either',
545
+ label: 'playbook memory', plural: 'playbook memories', ownedBy: 'either', role: 'entity',
543
546
  properties: {
544
547
  family: `${APCTX}memoryFamily`,
545
548
  rounds: `${APCTX}memoryRounds`,
@@ -548,50 +551,50 @@ export const VAULT_RECORD_BINDINGS = [
548
551
  // ── Card-room study records — the person's own play, read by a named coach service under a grant ──
549
552
  {
550
553
  match: { exact: 'cardroom.hand' }, class: `${APCTX}CardRoomHandRecord`,
551
- label: 'hand record', plural: 'hand records', ownedBy: 'person',
554
+ label: 'hand record', plural: 'hand records', ownedBy: 'person', role: 'entity',
552
555
  properties: { hands: `${APCTX}handsRecorded` },
553
556
  },
554
- { match: { exact: 'cardroom.style' }, class: `${APCTX}CardRoomStyleRecord`, label: 'playing style', plural: 'playing styles', ownedBy: 'person' },
555
- { match: { exact: 'cardroom.read' }, class: `${APCTX}CardRoomPlayerRead`, label: 'player read', plural: 'player reads', ownedBy: 'person' },
557
+ { match: { exact: 'cardroom.style' }, class: `${APCTX}CardRoomStyleRecord`, label: 'playing style', plural: 'playing styles', ownedBy: 'person', role: 'entity' },
558
+ { match: { exact: 'cardroom.read' }, class: `${APCTX}CardRoomPlayerRead`, label: 'player read', plural: 'player reads', ownedBy: 'person', role: 'entity' },
556
559
  {
557
560
  match: { exact: 'cardroom.note' }, class: `${APCTX}CardRoomCoachNote`,
558
- label: 'coach note', plural: 'coach notes', ownedBy: 'person',
561
+ label: 'coach note', plural: 'coach notes', ownedBy: 'person', role: 'entity',
559
562
  properties: { 'entries[].by': `${APCTX}coachedBy` },
560
563
  },
561
- { match: { exact: 'cardroom.client' }, class: `${APCTX}CardRoomCoachClient`, label: 'coaching client', plural: 'coaching clients', ownedBy: 'either' },
562
- { match: { prefix: 'cardroom.hands:' }, class: `${APCTX}CardRoomHandRecord`, label: 'a day’s hands', plural: 'days of hands', ownedBy: 'person' },
563
- { match: { exact: 'cardroom.prefs' }, class: `${APCTX}CardRoomPreferences`, label: 'card-room preferences', plural: 'card-room preferences', ownedBy: 'person' },
564
+ { match: { exact: 'cardroom.client' }, class: `${APCTX}CardRoomCoachClient`, label: 'coaching client', plural: 'coaching clients', ownedBy: 'either', role: 'entity' },
565
+ { match: { prefix: 'cardroom.hands:' }, class: `${APCTX}CardRoomHandRecord`, label: 'a day’s hands', plural: 'days of hands', ownedBy: 'person', role: 'entity' },
566
+ { match: { exact: 'cardroom.prefs' }, class: `${APCTX}CardRoomPreferences`, label: 'card-room preferences', plural: 'card-room preferences', ownedBy: 'person', role: 'entity' },
564
567
  // Who the person is as a player — ONE record across games (cr:PlayerProfile in the card-room ontology).
565
- { match: { exact: 'cardroom.profile' }, class: `${APCTX}CardRoomPlayerProfile`, label: 'player profile', plural: 'player profiles', ownedBy: 'person' },
568
+ { match: { exact: 'cardroom.profile' }, class: `${APCTX}CardRoomPlayerProfile`, label: 'player profile', plural: 'player profiles', ownedBy: 'person', role: 'entity' },
566
569
  // A CLUB, kept by its own workspace agent (apctx:CardRoomClub…): the profile, the rule it meets by, and
567
570
  // the nights as they diverge from the rule. The roster is the organization's own membership records.
568
- { match: { exact: 'cardroom.club.profile' }, class: `${APCTX}CardRoomClub`, label: 'club', plural: 'clubs', ownedBy: 'organization' },
569
- { match: { exact: 'cardroom.club.schedule' }, class: `${APCTX}CardRoomClubSchedule`, label: 'club schedule', plural: 'club schedules', ownedBy: 'organization' },
570
- { match: { exact: 'cardroom.club.nights' }, class: `${APCTX}CardRoomClubNights`, label: 'club nights', plural: 'club nights', ownedBy: 'organization' },
571
+ { match: { exact: 'cardroom.club.profile' }, class: `${APCTX}CardRoomClub`, label: 'club', plural: 'clubs', ownedBy: 'organization', role: 'entity' },
572
+ { match: { exact: 'cardroom.club.schedule' }, class: `${APCTX}CardRoomClubSchedule`, label: 'club schedule', plural: 'club schedules', ownedBy: 'organization', role: 'entity' },
573
+ { match: { exact: 'cardroom.club.nights' }, class: `${APCTX}CardRoomClubNights`, label: 'club nights', plural: 'club nights', ownedBy: 'organization', role: 'entity' },
571
574
  // A MISSION, kept by its own organization (apctx:CardRoomMission…): the presence a card room's map shows,
572
575
  // the steward's signed covenant, and the confidential contact — written in the registration ceremony.
573
- { match: { exact: 'cardroom.mission.presence' }, class: `${APCTX}CardRoomMission`, label: 'mission presence', plural: 'mission presences', ownedBy: 'organization' },
574
- { match: { exact: 'cardroom.mission.covenant' }, class: `${APCTX}CardRoomMissionCovenant`, label: 'mission covenant', plural: 'mission covenants', ownedBy: 'organization' },
575
- { match: { exact: 'cardroom.mission.contact' }, class: `${APCTX}CardRoomMissionContact`, label: 'mission contact', plural: 'mission contacts', ownedBy: 'organization' },
576
+ { match: { exact: 'cardroom.mission.presence' }, class: `${APCTX}CardRoomMission`, label: 'mission presence', plural: 'mission presences', ownedBy: 'organization', role: 'entity' },
577
+ { match: { exact: 'cardroom.mission.covenant' }, class: `${APCTX}CardRoomMissionCovenant`, label: 'mission covenant', plural: 'mission covenants', ownedBy: 'organization', role: 'entity' },
578
+ { match: { exact: 'cardroom.mission.contact' }, class: `${APCTX}CardRoomMissionContact`, label: 'mission contact', plural: 'mission contacts', ownedBy: 'organization', role: 'entity' },
576
579
  // ONE CABINET PER GAME: hold'em's study records are the bare names above; every other game's carry the
577
580
  // family — canasta's here, the same classes, a different coach's grant.
578
581
  {
579
582
  match: { exact: 'cardroom.canasta.hand' }, class: `${APCTX}CardRoomHandRecord`,
580
- label: 'canasta round record', plural: 'canasta round records', ownedBy: 'person',
583
+ label: 'canasta round record', plural: 'canasta round records', ownedBy: 'person', role: 'entity',
581
584
  properties: { hands: `${APCTX}handsRecorded` },
582
585
  },
583
- { match: { exact: 'cardroom.canasta.style' }, class: `${APCTX}CardRoomStyleRecord`, label: 'canasta playing style', plural: 'canasta playing styles', ownedBy: 'person' },
584
- { match: { exact: 'cardroom.canasta.read' }, class: `${APCTX}CardRoomPlayerRead`, label: 'canasta player read', plural: 'canasta player reads', ownedBy: 'person' },
586
+ { match: { exact: 'cardroom.canasta.style' }, class: `${APCTX}CardRoomStyleRecord`, label: 'canasta playing style', plural: 'canasta playing styles', ownedBy: 'person', role: 'entity' },
587
+ { match: { exact: 'cardroom.canasta.read' }, class: `${APCTX}CardRoomPlayerRead`, label: 'canasta player read', plural: 'canasta player reads', ownedBy: 'person', role: 'entity' },
585
588
  {
586
589
  match: { exact: 'cardroom.canasta.note' }, class: `${APCTX}CardRoomCoachNote`,
587
- label: 'canasta coach note', plural: 'canasta coach notes', ownedBy: 'person',
590
+ label: 'canasta coach note', plural: 'canasta coach notes', ownedBy: 'person', role: 'entity',
588
591
  properties: { 'entries[].by': `${APCTX}coachedBy` },
589
592
  },
590
- { match: { prefix: 'cardroom.canasta.hands:' }, class: `${APCTX}CardRoomHandRecord`, label: 'a day’s canasta rounds', plural: 'days of canasta rounds', ownedBy: 'person' },
593
+ { match: { prefix: 'cardroom.canasta.hands:' }, class: `${APCTX}CardRoomHandRecord`, label: 'a day’s canasta rounds', plural: 'days of canasta rounds', ownedBy: 'person', role: 'entity' },
591
594
  // ── Standing instructions (spec 394) — the owner's declared defaults, per room ──────────────────
592
595
  {
593
596
  match: { exact: 'standing.instructions' }, class: `${APCTX}StandingInstruction`,
594
- label: 'standing instruction', plural: 'standing instructions', ownedBy: 'person',
597
+ label: 'standing instruction', plural: 'standing instructions', ownedBy: 'person', role: 'entity',
595
598
  properties: {
596
599
  'entries[].capability': `${APCTX}instructionCapability`,
597
600
  'entries[].arg': `${APCTX}instructionArgument`,
@@ -603,7 +606,7 @@ export const VAULT_RECORD_BINDINGS = [
603
606
  // ── Declared routines (spec 402 W3 · 323 W6) — the owner's routines as a record that travels ─────
604
607
  {
605
608
  match: { exact: 'routines.data' }, class: `${APCTX}DeclaredRoutine`,
606
- label: 'declared routine', plural: 'declared routines', ownedBy: 'person',
609
+ label: 'declared routine', plural: 'declared routines', ownedBy: 'person', role: 'entity',
607
610
  properties: {
608
611
  'entries[].ask': `${APCTX}routineAsk`,
609
612
  'entries[].every': `${APCTX}routineEvery`,
@@ -614,13 +617,13 @@ export const VAULT_RECORD_BINDINGS = [
614
617
  // ── The person's preferences (spec 403 W2/W4) — nudges and how to answer ─────────────────────────
615
618
  {
616
619
  match: { exact: 'person.preferences' }, class: `${APCTX}PersonPreferences`,
617
- label: 'preferences', plural: 'preferences', ownedBy: 'person',
620
+ label: 'preferences', plural: 'preferences', ownedBy: 'person', role: 'entity',
618
621
  properties: { 'notify.email': `${APCTX}nudgeByEmail`, 'answer.style': `${APCTX}answerStyle`, 'answer.language': `${APCTX}answerLanguage` },
619
622
  },
620
623
  // ── Remembered facts (spec 402 W1) — what the owner's agent knows about the owner ────────────────
621
624
  {
622
625
  match: { exact: 'memory.facts' }, class: `${APCTX}RememberedFact`,
623
- label: 'remembered fact', plural: 'remembered facts', ownedBy: 'person',
626
+ label: 'remembered fact', plural: 'remembered facts', ownedBy: 'person', role: 'entity',
624
627
  properties: {
625
628
  'entries[].fact': `${APCTX}factWords`,
626
629
  'entries[].source': `${APCTX}factSource`,
@@ -634,8 +637,8 @@ export const VAULT_RECORD_BINDINGS = [
634
637
  // against. A rebuild is fine; this would be a bereavement. The Durable Object stays as the serving
635
638
  // projection, rebuilt from these records and never their only copy.
636
639
  {
637
- match: { prefix: 'federation.projection-submission:' }, class: `${APEST}ProjectionSubmission`,
638
- label: 'projection submission', plural: 'projection submissions', ownedBy: 'either',
640
+ match: { prefix: 'federation.projection-submission:' }, class: `${APEST}HeldProjectionSubmission`, // ⊑ apest:ProjectionSubmission, ap:HeldSecret (ONT-2)
641
+ label: 'projection submission', plural: 'projection submissions', ownedBy: 'either', role: 'secret', // carries the leaf's BLIND
639
642
  properties: {
640
643
  set: `${APEST}projectionSet`,
641
644
  digest: `${APEST}vouchedDigest`,
@@ -656,9 +659,11 @@ export const VAULT_RECORD_BINDINGS = [
656
659
  // holds only its digest; lose the device key and no presentation can ever be made; lose the secret and every
657
660
  // pairwise account at every verifier is unreachable. Bereavements, all three — vault records, never a cache.
658
661
  // None of these is read by any gate: the mandate is judged per signature by the presentation release (ADR-0041).
662
+ // The credential, the device key and the holder secret are `secret` (REM-2): held, used by the release under its
663
+ // own grant, and never opened by a question. The mandate, the issuer's records and the door's evidence are things.
659
664
  {
660
- match: { prefix: 'credential.anonymous:' }, class: `${APPC}AnonymousCredential`,
661
- label: 'anonymous credential', plural: 'anonymous credentials', ownedBy: 'person',
665
+ match: { prefix: 'credential.anonymous:' }, class: `${APPC}HeldAnonymousCredential`, // ⊑ appc:AnonymousCredential, ap:HeldSecret (ONT-2)
666
+ label: 'anonymous credential', plural: 'anonymous credentials', ownedBy: 'person', role: 'secret', // the credential itself, claim values included
662
667
  properties: {
663
668
  issuerKeyId: `${APPC}facetKeyId`,
664
669
  digest: `${APPC}credentialDigest`,
@@ -668,23 +673,24 @@ export const VAULT_RECORD_BINDINGS = [
668
673
  },
669
674
  },
670
675
  {
671
- match: { prefix: 'credential.device-key:' }, class: `${APPC}DeviceKey`,
672
- label: 'device key', plural: 'device keys', ownedBy: 'person',
676
+ match: { prefix: 'credential.device-key:' }, class: `${APPC}DeviceKeyMaterial`, // ⊑ appc:DeviceKey, ap:HeldSecret (ONT-2)
677
+ label: 'device key', plural: 'device keys', ownedBy: 'person', role: 'secret', // key material in a deployment that predates the managed key
673
678
  properties: { thumbprint: `${APPC}deviceKeyThumbprint`, createdAt: `${PROV}generatedAtTime` },
674
679
  },
675
- { match: { prefix: 'credential.holder-secret:' }, class: `${APPC}PairwiseAccount`, label: 'holder secret (pairwise accounts derive from it)', plural: 'holder secrets', ownedBy: 'person' },
680
+ // ONT-2: the SECRET (appc:HolderSecret ⊑ ap:HeldSecret), never the PairwiseAccount derived from it — the classes are disjoint.
681
+ { match: { prefix: 'credential.holder-secret:' }, class: `${APPC}HolderSecret`, label: 'holder secret (pairwise accounts derive from it)', plural: 'holder secrets', ownedBy: 'person', role: 'secret' },
676
682
  // Her standing `credential.present` wire — a delegation, kept under its own family because what it bounds (venues,
677
683
  // programs, facets) is this module's vocabulary. The release judges it per signature (ADR-0041); no gate reads it.
678
684
  {
679
685
  match: { prefix: 'credential.presentation-mandate:' }, class: `${APPC}PresentationMandate`,
680
- label: 'presentation mandate', plural: 'presentation mandates', ownedBy: 'person',
686
+ label: 'presentation mandate', plural: 'presentation mandates', ownedBy: 'person', role: 'entity',
681
687
  properties: { audiences: `${APPC}mandateAudience`, predicateDigests: `${APPC}mandatePredicateDigest`, issuerKeyIds: `${APPC}mandateIssuerKeyId`, maxPresentations: `${APPC}maxPresentations`, issuedAt: `${PROV}generatedAtTime` },
682
688
  },
683
689
  // THE ISSUER'S records: what the ORGANIZATION issued (spec 444) — one record per issuance, so it can revoke what it
684
690
  // issued; the member it went to, never the claim values (those are the holder's).
685
691
  {
686
692
  match: { prefix: 'credential.issued:' }, class: `${APPC}Issuance`,
687
- label: 'issued credential', plural: 'issued credentials', ownedBy: 'organization',
693
+ label: 'issued credential', plural: 'issued credentials', ownedBy: 'organization', role: 'entity',
688
694
  properties: {
689
695
  digest: `${APPC}issuedDigest`,
690
696
  issuerKeyId: `${APPC}facetKeyId`,
@@ -699,7 +705,7 @@ export const VAULT_RECORD_BINDINGS = [
699
705
  // to revoke) — the live set's leaves are `federation.projection-submission:` rows in the `live-credential` set.
700
706
  {
701
707
  match: { prefix: 'credential.issuer-facet:' }, class: `${APPC}IssuerKeyFacet`,
702
- label: 'issuer key facet', plural: 'issuer key facets', ownedBy: 'organization',
708
+ label: 'issuer key facet', plural: 'issuer key facets', ownedBy: 'organization', role: 'entity',
703
709
  properties: {
704
710
  keyId: `${APPC}facetKeyId`,
705
711
  thumbprint: `${APPC}facetPublicKeyThumbprint`,
@@ -712,7 +718,7 @@ export const VAULT_RECORD_BINDINGS = [
712
718
  // THE DOOR'S record of a predicate held — beside the admission decision; the digests, never the bundle.
713
719
  {
714
720
  match: { prefix: 'door.credential:' }, class: `${APPC}PredicateAdmissionEvidence`,
715
- label: 'predicate admission', plural: 'predicate admissions', ownedBy: 'either',
721
+ label: 'predicate admission', plural: 'predicate admissions', ownedBy: 'either', role: 'entity',
716
722
  properties: {
717
723
  issuerKeyId: `${APPC}facetKeyId`,
718
724
  predicateDigest: `${APPC}evidencePredicateDigest`,
@@ -731,7 +737,7 @@ export const VAULT_RECORD_BINDINGS = [
731
737
  // verifier (ADR-0041): what the agent may DO at a door is a mandate, judged per step.
732
738
  {
733
739
  match: { prefix: 'identity.client-key-binding:' }, class: `${AP}ClientKeyBinding`,
734
- label: 'client key binding', plural: 'client key bindings', ownedBy: 'either',
740
+ label: 'client key binding', plural: 'client key bindings', ownedBy: 'either', role: 'entity',
735
741
  properties: {
736
742
  clientId: `${AP}clientId`,
737
743
  jwkThumbprint: `${AP}jwkThumbprint`,
@@ -742,10 +748,11 @@ export const VAULT_RECORD_BINDINGS = [
742
748
  },
743
749
  },
744
750
  // The secret her pairwise subjects derive from — one record, per person; a rotation is a new `sub` everywhere.
745
- { match: { exact: 'identity.pairwise-secret' }, class: `${AP}PairwiseSubject`, label: 'pairwise secret (company subjects derive from it)', plural: 'pairwise secrets', ownedBy: 'person' },
751
+ // ONT-2: ap:PairwiseSecret ⊑ ap:HeldSecret, disjoint from the ap:PairwiseSubject derived from it.
752
+ { match: { exact: 'identity.pairwise-secret' }, class: `${AP}PairwiseSecret`, label: 'pairwise secret (company subjects derive from it)', plural: 'pairwise secrets', ownedBy: 'person', role: 'secret' },
746
753
  {
747
754
  match: { prefix: 'identity.external-account-link:' }, class: `${AP}ExternalAccountLink`,
748
- label: 'account at a company', plural: 'accounts at companies', ownedBy: 'person',
755
+ label: 'account at a company', plural: 'accounts at companies', ownedBy: 'person', role: 'entity',
749
756
  properties: {
750
757
  issuer: `${AP}pairwiseIssuer`,
751
758
  pairwiseSubjectDigest: `${AP}pairwiseSubjectDigest`,
@@ -779,16 +786,35 @@ export function askableRecordKinds() {
779
786
  const seen = new Set();
780
787
  const out = [];
781
788
  for (const b of VAULT_RECORD_BINDINGS) {
782
- // An index is not a thing to ask about — see `VaultRecordRole`.
783
- if ((b.role ?? 'entity') !== 'entity' || seen.has(b.class))
789
+ // An index is not a thing to ask about, and a secret is never told — see `VaultRecordRole`.
790
+ if (b.role !== 'entity' || seen.has(b.class))
784
791
  continue;
785
792
  seen.add(b.class);
786
793
  out.push({ label: b.label, plural: b.plural, class: b.class });
787
794
  }
788
795
  return out;
789
796
  }
790
- /** Every record type bound to this class — what a query over a kind must actually read. */
797
+ /** Every record type bound to this class THAT A QUESTION MAY READ — what a query over a kind must actually read.
798
+ * A class is often bound twice (the thing and its index): only the `entity` rows. A secret has its own class
799
+ * under `ap:HeldSecret` (ONT-2), so it never shares one with an entity. */
791
800
  export function recordTypesForClass(classIri) {
792
- return VAULT_RECORD_BINDINGS.filter((b) => b.class === classIri);
801
+ return VAULT_RECORD_BINDINGS.filter((b) => b.class === classIri && b.role === 'entity');
802
+ }
803
+ /** Is this record key one that is held and never told (`role: 'secret'`)? The check every reader that hands a
804
+ * record's content — or its key — to a model makes at the point of use (REM-2). */
805
+ export function isSecretRecordType(recordType) {
806
+ return bindingForRecordType(recordType)?.role === 'secret';
807
+ }
808
+ /** Rows that carry no decision about what they are FOR — none, in a table that compiles. For a gate
809
+ * (`check:ontology-bindings`) and the unit test: a row built outside the compiler's sight (a cast, a JSON import,
810
+ * a JS caller) must not reach the table as askable-by-default. */
811
+ export function bindingsWithoutRole(rows = VAULT_RECORD_BINDINGS) {
812
+ return rows
813
+ .filter((b) => !VAULT_RECORD_ROLES.includes(b.role))
814
+ .map((b) => b.match?.exact ?? b.match?.prefix ?? '(no key)');
815
+ }
816
+ /** The record kinds classified secret — for a gate, a doc, or a grant builder that must leave them out. */
817
+ export function secretRecordKinds() {
818
+ return VAULT_RECORD_BINDINGS.filter((b) => b.role === 'secret');
793
819
  }
794
820
  //# sourceMappingURL=vault-records.js.map