@agenticprimitives/ontology 1.0.0-alpha.37 → 1.0.0-alpha.39

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.
@@ -0,0 +1,436 @@
1
+ # T-box — the ANONYMOUS CREDENTIAL plane: what a holder proves about a credential without showing it, and every record
2
+ # the substrate keeps around that proof. Spec 304 (issuer-key facets), spec 305 (privacy credentials, W2 = the
3
+ # zero-knowledge suite), spec 442 §7.2 (the `predicate` proof grade at a company's door), spec 443 W5 (the door),
4
+ # docs/architecture/zkid-and-verifiable-credentials-alignment.md (waves Z1–Z4). Namespace appc:.
5
+ #
6
+ # ── The doctrine, in one line ─────────────────────────────────────────────────────────────────────
7
+ # PROOF IS EVIDENCE, THE MANDATE IS AUTHORITY, THE RECEIPT BINDS THE TWO. A presentation that verifies says "a
8
+ # credential under this issuer facet satisfies this predicate program, answering this verifier's challenge" — and
9
+ # nothing else: no claim value, no credential, no person. Whether the holder may ACT is her mandate's to say, judged
10
+ # per step (ADR-0041); whether she may ENTER is the door's admission on the evidence (ADR-0056 / ADR-0057). No gate
11
+ # reads an appc: record as a permission.
12
+ #
13
+ # ── What is deliberately NOT here ─────────────────────────────────────────────────────────────────
14
+ # · No property from a pairwise account or a presentation to the PERSON. The verifier learns a handle and a proof; the
15
+ # link to the person exists in her own vault and nowhere in a shared graph (INV-305-1/-3, ADR-0025). A vocabulary
16
+ # that offered the join would be an invitation to make it.
17
+ # · No claim values. A predicate program names claims and operators; a presentation proves the program held; the
18
+ # values stay in the credential, which stays with the holder.
19
+ # · No product or implementation name. Suites and grades are codelists (cbox/controlled-vocabularies.ttl); the
20
+ # proving system behind a suite is informative and lives in the packages that bind it.
21
+ #
22
+ # ── Where the records live (ADR-0055) ─────────────────────────────────────────────────────────────
23
+ # A facet document and its attestation are public (the issuer's chain). A credential and its device key are the
24
+ # HOLDER's vault records. A presentation is computed per challenge and held by a door for minutes under a reference —
25
+ # a cache; the receipt keeps the digests. The issuer row's openings are the ISSUER's vault records (apest:). A
26
+ # predicate admission's evidence is the door's receipt, beside the decision.
27
+
28
+ @prefix appc: <https://agenticprimitives.dev/ns/privacy-credential#> .
29
+ @prefix apvc: <https://agenticprimitives.dev/ns/verifiable-credential#> .
30
+ @prefix apatt: <https://agenticprimitives.dev/ns/attestation#> .
31
+ @prefix apdel: <https://agenticprimitives.dev/ns/delegation#> .
32
+ @prefix apest: <https://agenticprimitives.dev/ns/estate#> .
33
+ @prefix apix: <https://agenticprimitives.dev/ns/interaction#> .
34
+ @prefix ap: <https://agenticprimitives.dev/ns/core#> .
35
+ @prefix prov: <http://www.w3.org/ns/prov#> .
36
+ @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
37
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
38
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
39
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
40
+
41
+ appc: a owl:Ontology ;
42
+ rdfs:label "Agentic Primitives — anonymous credentials" ;
43
+ owl:versionInfo "0.1.0" ;
44
+ rdfs:comment "Issuer-key facets, holder-bound credentials, proof requests and predicate programs, zero-knowledge presentations with their nullifiers and status, the issuer's live-credential row, the presentation mandate, and the predicate as admission evidence. Specs 304 / 305 / 442 §7.2 / 443 W5." .
45
+
46
+ # ═══ The issuer side ══════════════════════════════════════════════════════════════════════════════
47
+
48
+ appc:IssuerKeyFacet a owl:Class ;
49
+ rdfs:subClassOf prov:Entity ;
50
+ rdfs:label "IssuerKeyFacet" ;
51
+ rdfs:comment "A KEY AN ISSUING AGENT SIGNS CREDENTIALS WITH, published as a facet of that agent (spec 304): one suite per facet, a public key, a validity window, and the agent's own signature over the facet's hash. A facet rotates; the issuing agent does not (ADR-0010/0011) — the facet is a credential of the agent, never its identity, and never a control credential (that is apcr:CredentialFacet). A verifier resolves it by key id and RE-VERIFIES it through the chain: the signature answers under the agent's account, and the facet is anchored as an attestation (appc:anchoredBy) — never a fetch to the issuer." .
52
+
53
+ appc:facetSubject a owl:ObjectProperty ;
54
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range ap:Agent ;
55
+ rdfs:label "facet subject" ;
56
+ rdfs:comment "The agent this key speaks for: an organization or a service. NEVER a person — a person's agent HOLDS credentials; it does not issue them (spec 443 §2). And never an estate's governance agent, whose row on neutral ground the issuer's own row would collide with (spec 443 W5)." .
57
+
58
+ appc:facetKeyId a owl:DatatypeProperty ;
59
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range xsd:string ;
60
+ rdfs:label "facet key id" ;
61
+ rdfs:comment "The id a credential names its issuer key by and a verifier resolves the facet by (`issuer-key:<suite>:<label>`). A name for lookup, never a trust signal." .
62
+
63
+ appc:facetSuite a owl:ObjectProperty ;
64
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range skos:Concept ;
65
+ rdfs:label "facet suite" ;
66
+ rdfs:comment "ONE suite per facet (INV-304-3), from appc:issuerKeySuiteScheme. A key reused across suites is two facets and two attestations." .
67
+
68
+ appc:facetPublicKeyThumbprint a owl:DatatypeProperty ;
69
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range xsd:string ;
70
+ rdfs:label "facet public key thumbprint" ;
71
+ rdfs:comment "The JWK thumbprint of the facet's public key: what a listing shows and what a proof's hidden issuer key is checked against after verification. The key itself is in the facet document; never a private component." .
72
+
73
+ appc:facetHash a owl:DatatypeProperty ;
74
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range xsd:string ;
75
+ rdfs:label "facet hash" ;
76
+ rdfs:comment "sha256 over the canonical facet document — what the issuing agent signed and what the attestation's credentialHash carries. A document that recomputes to another hash is not this facet." .
77
+
78
+ appc:facetValidFrom a owl:DatatypeProperty ;
79
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range xsd:dateTime ;
80
+ rdfs:label "facet valid from" .
81
+
82
+ appc:facetValidUntil a owl:DatatypeProperty ;
83
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range xsd:dateTime ;
84
+ rdfs:label "facet valid until" ;
85
+ rdfs:comment "Absent means open-ended; revocation is the attestation's revoke path, which a verifier reads at verification time (spec 304 §rotation)." .
86
+
87
+ appc:anchoredBy a owl:ObjectProperty ;
88
+ rdfs:domain appc:IssuerKeyFacet ; rdfs:range apatt:Attestation ;
89
+ rdfs:label "anchored by" ;
90
+ rdfs:comment "The attestation on the issuer's chain that binds the facet to the agent: credentialType `issuer-key-facet`, subject = issuer = the agent, credentialHash = appc:facetHash. Live (not revoked) is what a verifier checks; the uid is what the register lists. Anchoring is the only way a stranger learns a facet is the agent's — the facet document alone proves nothing." .
91
+
92
+ appc:IssuerRow a owl:Class ;
93
+ rdfs:subClassOf prov:Entity ;
94
+ rdfs:label "IssuerRow" ;
95
+ rdfs:comment "A CREDENTIAL ISSUER'S LIVE-CREDENTIAL ROOT ON NEUTRAL GROUND — the issuer's own row on the estate projection registry, keyed by the same id function as an estate's (chain + agent) and TAGGED as an issuer row so a verifier can tell it from an estate's (a credential leaf is never standing; a door refuses a row so tagged as if it were an estate). Its leaves are apest:ProjectionSubmission records in the `live-credential` set, kept by the issuer with their openings; the root is anchored under a monotonic sequence. REVOCATION IS THE ISSUER'S ACT: it retires a leaf and re-anchors, and every status presentation built at an older sequence is stale against the chain from then on. Zero-knowledge alignment §4, wave Z3." .
96
+
97
+ appc:issuerRowOf a owl:ObjectProperty ;
98
+ rdfs:domain appc:IssuerRow ; rdfs:range ap:Agent ;
99
+ rdfs:label "issuer row of" ;
100
+ rdfs:comment "The issuing agent whose live set this is; the row's signer on neutral ground is the agent itself, and the key that writes is a delegate under its anchoring wire (spec 439 §4)." .
101
+
102
+ appc:issuerRowId a owl:DatatypeProperty ;
103
+ rdfs:domain appc:IssuerRow ; rdfs:range xsd:string ;
104
+ rdfs:label "issuer row id" ;
105
+ rdfs:comment "keccak256(`eip155:<chainId>:<issuer agent>`) — the registry key. The only thing public ground learns about the issuer's set." .
106
+
107
+ appc:liveCredentialRoot a owl:DatatypeProperty ;
108
+ rdfs:domain appc:IssuerRow ; rdfs:range xsd:string ;
109
+ rdfs:label "live-credential root" ;
110
+ rdfs:comment "The anchored Merkle root over the commitments of the credentials the issuer still stands behind, as of appc:anchoredSequence." .
111
+
112
+ appc:anchoredSequence a owl:DatatypeProperty ;
113
+ rdfs:domain appc:IssuerRow ; rdfs:range xsd:integer ;
114
+ rdfs:label "anchored sequence" ;
115
+ rdfs:comment "Strictly increasing per anchor. A status presentation names the sequence it was built at; a verifier accepts only the sequence it READ, within its freshness window — behind is stale, ahead is unverifiable, neither is fetched." .
116
+
117
+ appc:anchoredAt a owl:DatatypeProperty ;
118
+ rdfs:domain appc:IssuerRow ; rdfs:range xsd:dateTime ;
119
+ rdfs:label "anchored at" .
120
+
121
+ appc:hasLiveCredentialLeaf a owl:ObjectProperty ;
122
+ rdfs:domain appc:IssuerRow ; rdfs:range apest:ProjectionSubmission ;
123
+ rdfs:label "has live-credential leaf" ;
124
+ rdfs:comment "A leaf of the row: an apest:ProjectionSubmission whose apest:projectionSet is `live-credential` and whose apest:vouchedDigest is the credential digest (appc:credentialDigest). The issuer's record, with the opening; absent from the chain." .
125
+
126
+ # ═══ The holder side ══════════════════════════════════════════════════════════════════════════════
127
+
128
+ appc:AnonymousCredential a owl:Class ;
129
+ rdfs:subClassOf apvc:VerifiableCredential ;
130
+ rdfs:label "AnonymousCredential" ;
131
+ rdfs:comment "A CREDENTIAL MADE TO BE PROVED ABOUT, NOT SHOWN: issued under an issuer-key facet, with its claims selectively disclosable and the HOLDER'S DEVICE KEY bound into it, so that a presentation can prove a predicate over the claims and possession of the key without revealing either. The holder's vault record (ADR-0055): the issuer keeps its digest in its live set, never the credential." .
132
+
133
+ appc:issuedUnder a owl:ObjectProperty ;
134
+ rdfs:domain appc:AnonymousCredential ; rdfs:range appc:IssuerKeyFacet ;
135
+ rdfs:label "issued under" ;
136
+ rdfs:comment "The facet whose key signed the credential. A presentation names the facet's key id; the proof hides the key and the verifier checks the proven key against the resolved facet (spec 304 step 4)." .
137
+
138
+ appc:boundToDeviceKey a owl:ObjectProperty ;
139
+ rdfs:domain appc:AnonymousCredential ; rdfs:range appc:DeviceKey ;
140
+ rdfs:label "bound to device key" ;
141
+ rdfs:comment "Holder binding: the public key in the credential's confirmation claim. A presentation is valid only with a signature by this key over the verifier's challenge — made inside the proof, so the key stays hidden." .
142
+
143
+ appc:credentialDigest a owl:DatatypeProperty ;
144
+ rdfs:domain appc:AnonymousCredential ; rdfs:range xsd:string ;
145
+ rdfs:label "credential digest" ;
146
+ rdfs:comment "keccak256 over the issuer-signed compact credential (never the disclosures, which the holder chooses per presentation). Issuer and holder compute the same; it is the leaf of the issuer row's live set and the key of a status presentation." .
147
+
148
+ appc:claimSchema a owl:DatatypeProperty ;
149
+ rdfs:range xsd:string ;
150
+ rdfs:label "claim schema" ;
151
+ rdfs:comment "The issuer-fixed disclosure order of a credential type — claim name per slot, as a JSON array string. A verifier knows the credential format and resolves claim names to slots directly; a request and a credential that disagree on it prove nothing. Declared on the credential and on the proof request." .
152
+
153
+ appc:DeviceKey a owl:Class ;
154
+ rdfs:subClassOf prov:Entity ;
155
+ rdfs:label "DeviceKey" ;
156
+ rdfs:comment "THE HOLDER-BINDING KEY — custodied (a managed signer, or a local signer standing in for one), never held by the agent that presents. It signs ONLY under a presentation mandate (appc:PresentationMandate), judged by the presentation release inside every signature; the proving system sees a callback, never the key. Named by its thumbprint. It is a credential of the holder's, never her identity, and no property here leads from it to her." .
157
+
158
+ appc:deviceKeyThumbprint a owl:DatatypeProperty ;
159
+ rdfs:domain appc:DeviceKey ; rdfs:range xsd:string ;
160
+ rdfs:label "device key thumbprint" .
161
+
162
+ appc:PairwiseAccount a owl:Class ;
163
+ rdfs:subClassOf prov:Entity ;
164
+ rdfs:label "PairwiseAccount" ;
165
+ rdfs:comment "THE ACCOUNT A VERIFIER SEES: derived from the holder's secret and the verifier's origin, one per verifier, unlinkable across verifiers (INV-305-1), underivable without the secret. It signs the request proof at a door — the admission invariants want a signed actor (ADR-0010/0041) and this is the actor — and it appears in the door's receipt. It is NOT a Smart Agent and not the person: the link from it to her exists only in her vault, and this vocabulary declares no property for it on purpose." .
166
+
167
+ appc:pairwiseFor a owl:DatatypeProperty ;
168
+ rdfs:domain appc:PairwiseAccount ; rdfs:range xsd:anyURI ;
169
+ rdfs:label "pairwise for" ;
170
+ rdfs:comment "The verifier's origin the account exists for. The same holder at another origin is another account." .
171
+
172
+ # ═══ The exchange: request → presentation ═════════════════════════════════════════════════════════
173
+
174
+ appc:ProofRequest a owl:Class ;
175
+ rdfs:subClassOf prov:Entity ;
176
+ rdfs:label "ProofRequest" ;
177
+ rdfs:comment "WHAT A VERIFIER ASKS — built by the verifier from ITS OWN policy and ITS OWN challenge, never from a presentation: one suite, the predicates to prove, the credential layout accepted, the proof-bundle versions bound to its verifying keys, an audience (the verifier's origin) and a single-use nonce. The holder reproduces it from the verifier's published policy so both sides digest the same predicate program." .
178
+
179
+ appc:requestSuite a owl:ObjectProperty ;
180
+ rdfs:domain appc:ProofRequest ; rdfs:range skos:Concept ;
181
+ rdfs:label "request suite" ;
182
+ rdfs:comment "ONE suite per request (ADR-0013 — no ladder), from appc:presentationSuiteScheme. A presentation in any other suite is refused, never downgraded." .
183
+
184
+ appc:verifierId a owl:DatatypeProperty ;
185
+ rdfs:domain appc:ProofRequest ; rdfs:range xsd:string ;
186
+ rdfs:label "verifier id" .
187
+
188
+ appc:audience a owl:DatatypeProperty ;
189
+ rdfs:range xsd:anyURI ;
190
+ rdfs:label "audience" ;
191
+ rdfs:comment "The verifier's origin the proof is bound to. On the request, the nullifier, the status presentation and the mandate alike: a thing made for one audience answers no other." .
192
+
193
+ appc:challengeNonce a owl:DatatypeProperty ;
194
+ rdfs:domain appc:ProofRequest ; rdfs:range xsd:string ;
195
+ rdfs:label "challenge nonce" ;
196
+ rdfs:comment "Single-use. The verifier consumes it before a proof is verified, so the same challenge is never answered twice (1/OPENAC §Challenge Freshness as deployment policy)." .
197
+
198
+ appc:asksPredicate a owl:ObjectProperty ;
199
+ rdfs:domain appc:ProofRequest ; rdfs:range appc:PredicateProgram ;
200
+ rdfs:label "asks predicate" .
201
+
202
+ appc:acceptedBundleVersion a owl:DatatypeProperty ;
203
+ rdfs:domain appc:ProofRequest ; rdfs:range xsd:string ;
204
+ rdfs:label "accepted bundle version" ;
205
+ rdfs:comment "A proof-bundle version this verifier has bound to its tuple of verifying keys, circuit parameters, profile and challenge pipeline. Anything unbound is refused (1/OPENAC §Versioning). Repeatable." .
206
+
207
+ appc:PredicateProgram a owl:Class ;
208
+ rdfs:subClassOf prov:Entity ;
209
+ rdfs:label "PredicateProgram" ;
210
+ rdfs:comment "THE STATEMENT PROVED: a conjunction of predicates over named claims, compiled to the suite's canonical form and digested. The digest is what a holder's mandate names and what a receipt cites — the same program at the same verifier is the same reason, which is what makes a mandate standing across challenges rather than a signature per nonce." .
211
+
212
+ appc:predicateDigest a owl:DatatypeProperty ;
213
+ rdfs:range xsd:string ;
214
+ rdfs:label "predicate digest" ;
215
+ rdfs:comment "The intent digest of the compiled, canonical program. Computed by the verifier from its own request and by the holder from the published policy; a disagreement derives no mandate." .
216
+
217
+ appc:hasPredicate a owl:ObjectProperty ;
218
+ rdfs:domain appc:PredicateProgram ; rdfs:range appc:Predicate ;
219
+ rdfs:label "has predicate" .
220
+
221
+ appc:Predicate a owl:Class ;
222
+ rdfs:subClassOf prov:Entity ;
223
+ rdfs:label "Predicate" ;
224
+ rdfs:comment "One claim, one operator, one operand: `age gte 18`. No claim VALUE of the holder's appears anywhere in this vocabulary — the operand is the verifier's threshold." .
225
+
226
+ appc:predicateClaim a owl:DatatypeProperty ;
227
+ rdfs:domain appc:Predicate ; rdfs:range xsd:string ;
228
+ rdfs:label "predicate claim" .
229
+
230
+ appc:predicateOp a owl:ObjectProperty ;
231
+ rdfs:domain appc:Predicate ; rdfs:range skos:Concept ;
232
+ rdfs:label "predicate operator" ;
233
+ rdfs:comment "From appc:predicateOpScheme: gte · lte · in-set · before · after." .
234
+
235
+ appc:predicateOperand a owl:DatatypeProperty ;
236
+ rdfs:domain appc:Predicate ; rdfs:range xsd:string ;
237
+ rdfs:label "predicate operand" ;
238
+ rdfs:comment "The threshold, set member list or date, as the suite's lexical form. A literal out of the suite's range is a refusal (`predicate_invalid`), not a wider circuit." .
239
+
240
+ appc:PrivatePresentation a owl:Class ;
241
+ rdfs:subClassOf prov:Entity ;
242
+ rdfs:label "PrivatePresentation" ;
243
+ rdfs:comment "WHAT A HOLDER ANSWERS WITH: a proof that a credential under the named facet satisfies the request's predicate program and that the device key signed the request's audience-bound challenge — the issuer key, the device key and every claim hidden; plus, when the verifier's policy asks, a nullifier for this audience and the issuer's status presentation. Computed per challenge, never stored by the holder; held by a door for minutes under a reference (a cache); only its digest survives in a receipt. It says nothing about who presented." .
244
+
245
+ appc:answersRequest a owl:ObjectProperty ;
246
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:ProofRequest ;
247
+ rdfs:label "answers request" ;
248
+ rdfs:comment "The one request this proof answers; the audience and nonce inside the proof must be the request's (`nonce_or_audience_mismatch` otherwise)." .
249
+
250
+ appc:presentedUnder a owl:ObjectProperty ;
251
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:IssuerKeyFacet ;
252
+ rdfs:label "presented under" ;
253
+ rdfs:comment "The facet the presentation claims, by key id. The verifier resolves it through the chain and checks the proven issuer key against it; a reference naming another facet than the verdict's is refused." .
254
+
255
+ appc:provesPredicate a owl:ObjectProperty ;
256
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:PredicateProgram ;
257
+ rdfs:label "proves predicate" ;
258
+ rdfs:comment "The program that held — `expression_result = 1` inside the proof. Evidence that the predicate holds, never policy acceptance (that is the verifier's), never authority." .
259
+
260
+ appc:bundleVersion a owl:DatatypeProperty ;
261
+ rdfs:domain appc:PrivatePresentation ; rdfs:range xsd:string ;
262
+ rdfs:label "bundle version" .
263
+
264
+ appc:relationshipHandle a owl:DatatypeProperty ;
265
+ rdfs:domain appc:PrivatePresentation ; rdfs:range xsd:string ;
266
+ rdfs:label "relationship handle" ;
267
+ rdfs:comment "The pairwise pseudonym for THIS verifier when the holder chooses to carry one (INV-305-3) — never her agent." .
268
+
269
+ appc:carriesNullifier a owl:ObjectProperty ;
270
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:Nullifier ;
271
+ rdfs:label "carries nullifier" .
272
+
273
+ appc:carriesStatus a owl:ObjectProperty ;
274
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:CredentialStatusPresentation ;
275
+ rdfs:label "carries status" .
276
+
277
+ appc:signedByDeviceKey a owl:ObjectProperty ;
278
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:DeviceKey ;
279
+ rdfs:label "signed by device key" ;
280
+ rdfs:comment "The holder's own record of which custodied key answered the challenge — inside the proof the key is hidden, so this relation lives in her vault, never in what a verifier holds." .
281
+
282
+ appc:madeUnderMandate a owl:ObjectProperty ;
283
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:PresentationMandate ;
284
+ rdfs:label "made under mandate" ;
285
+ rdfs:comment "The child mandate the device key signed under — the holder's receipt joins the proof digest, the challenge digest and this mandate's digest (apvr:, spec 305 §Z2). The verifier never sees the mandate; it is the holder's evidence that her agent acted within what she allowed." .
286
+
287
+ appc:presents a owl:ObjectProperty ;
288
+ rdfs:subPropertyOf prov:wasDerivedFrom ;
289
+ rdfs:domain appc:PrivatePresentation ; rdfs:range appc:AnonymousCredential ;
290
+ rdfs:label "presents" ;
291
+ rdfs:comment "Which credential the proof was made from — the holder's record only. A verifier that could state this triple would have unlinked nothing." .
292
+
293
+ appc:Nullifier a owl:Class ;
294
+ rdfs:subClassOf prov:Entity ;
295
+ rdfs:label "Nullifier" ;
296
+ rdfs:comment "ONE VISIT PER AUDIENCE: a value deterministic per (device key, audience) — a hash of the device key's signature over an audience-bound message — that a verifier's store consumes atomically. The same holder at the same audience within the policy's window is `nullifier_reused`; at another audience the value differs and nothing links them. Its GRADE says how much it is worth: `asserted` is honest-holder-exact (the verifier checks nothing about its derivation), `in-circuit` is proved inside the presentation (2/ZK-POP; reserved until the profile emits it). The STORE is the verifier's (a door's ledger), never the verifying service's." .
297
+
298
+ appc:nullifierValue a owl:DatatypeProperty ;
299
+ rdfs:domain appc:Nullifier ; rdfs:range xsd:string ;
300
+ rdfs:label "nullifier value" .
301
+
302
+ appc:nullifierGrade a owl:ObjectProperty ;
303
+ rdfs:domain appc:Nullifier ; rdfs:range skos:Concept ;
304
+ rdfs:label "nullifier grade" ;
305
+ rdfs:comment "From appc:nullifierGradeScheme. A verifier's policy names the lowest grade it accepts; `in-circuit` refuses every asserted one." .
306
+
307
+ appc:CredentialStatusPresentation a owl:Class ;
308
+ rdfs:subClassOf prov:Entity ;
309
+ rdfs:label "CredentialStatusPresentation" ;
310
+ rdfs:comment "THE ISSUER STILL STANDS BEHIND THIS CREDENTIAL, as of a sequence: one leaf of the issuer row, its opening, a Merkle proof against the anchored root, bound to the verifier's challenge. Names no subject — a credential is not a person. The verifier reads the root from neutral ground, never from the holder: a presentation behind the anchored sequence is `stale` (what a revoked credential's old status becomes), ahead is unverifiable, and neither is fetched. Linkable under the Merkle suite (the opening names the credential) — said, and the reason a verifier asks for it only where it would otherwise phone a status list; the zero-knowledge form is reserved." .
311
+
312
+ appc:statusOf a owl:ObjectProperty ;
313
+ rdfs:domain appc:CredentialStatusPresentation ; rdfs:range appc:IssuerRow ;
314
+ rdfs:label "status of" .
315
+
316
+ appc:statusSequence a owl:DatatypeProperty ;
317
+ rdfs:domain appc:CredentialStatusPresentation ; rdfs:range xsd:integer ;
318
+ rdfs:label "status sequence" ;
319
+ rdfs:comment "The anchored sequence the proof was built against; a verifier accepts the sequence it read and refuses every other." .
320
+
321
+ # ═══ Authority around the proof (never the proof itself) ══════════════════════════════════════════
322
+
323
+ appc:PresentationMandate a owl:Class ;
324
+ rdfs:subClassOf apdel:Delegation ;
325
+ rdfs:label "PresentationMandate" ;
326
+ rdfs:comment "THE PERSON'S STANDING PERMISSION FOR HER DEVICE KEY TO SIGN (capability `credential.present`): a delegation from her agent to her runtime's key bounded to the verifiers, the predicate programs and the issuer facets she agreed to, for a window. Her runtime derives a CHILD for one statement (one audience, one program, one facet, a few minutes) and the presentation release judges that child before EVERY device-key signature — the key is behind the release, the proving system gets a callback. A wire for another venue signs nothing (the release refuses; nothing is presented). Delegated presentation, zero-knowledge alignment §3, wave Z2." .
327
+
328
+ appc:mandateAudience a owl:DatatypeProperty ;
329
+ rdfs:domain appc:PresentationMandate ; rdfs:range xsd:anyURI ;
330
+ rdfs:label "mandate audience" ;
331
+ rdfs:comment "A verifier origin the mandate covers. Repeatable on a standing wire; exactly one on a derived child." .
332
+
333
+ appc:mandatePredicateDigest a owl:DatatypeProperty ;
334
+ rdfs:domain appc:PresentationMandate ; rdfs:range xsd:string ;
335
+ rdfs:label "mandate predicate digest" ;
336
+ rdfs:comment "A predicate program the mandate covers, by its digest (appc:predicateDigest). The holder proves no program she did not agree to." .
337
+
338
+ appc:mandateIssuerKeyId a owl:DatatypeProperty ;
339
+ rdfs:domain appc:PresentationMandate ; rdfs:range xsd:string ;
340
+ rdfs:label "mandate issuer key id" ;
341
+ rdfs:comment "A facet (appc:facetKeyId) the mandate covers presenting under." .
342
+
343
+ appc:maxPresentations a owl:DatatypeProperty ;
344
+ rdfs:domain appc:PresentationMandate ; rdfs:range xsd:integer ;
345
+ rdfs:label "max presentations" ;
346
+ rdfs:comment "How many presentations the mandate allows; 0 on a standing wire means unbounded within its window, 1 on a derived child." .
347
+
348
+ appc:PresentationRelease a owl:Class ;
349
+ rdfs:subClassOf prov:Activity ;
350
+ rdfs:label "PresentationRelease" ;
351
+ rdfs:comment "ONE JUDGEMENT OF THE MANDATE FOR ONE SIGNATURE: the release checks the child mandate against the statement (audience · predicate digest · facet), its signature, its revocation on chain and its window, then signs the audience-bound challenge with the device key — or refuses with a code (`mandate-denied`, `challenge-unbound`, `audience-mismatch`, `approval-required`). Every decision, allowed or refused, is the receipt's raw material." .
352
+
353
+ appc:releasedUnder a owl:ObjectProperty ;
354
+ rdfs:domain appc:PresentationRelease ; rdfs:range appc:PresentationMandate ;
355
+ rdfs:label "released under" .
356
+
357
+ appc:releaseOutcome a owl:DatatypeProperty ;
358
+ rdfs:domain appc:PresentationRelease ; rdfs:range xsd:string ;
359
+ rdfs:label "release outcome" ;
360
+ rdfs:comment "`allow`, or the refusal code. A refusal signs nothing." .
361
+
362
+ # ═══ The verifier's policy, and the predicate as admission evidence ═══════════════════════════════
363
+
364
+ appc:VerifierPolicy a owl:Class ;
365
+ rdfs:subClassOf prov:Entity ;
366
+ rdfs:label "VerifierPolicy" ;
367
+ rdfs:comment "WHAT A VERIFIER (a door) ASKS AND ACCEPTS, declared where a holder can read it: the predicate program, the credential layout, the accepted bundle versions, whether a nullifier is required and at which grade and window, whether the issuer's status is required and how fresh, which issuer facets it trusts, and where the proof is verified. 1/OPENAC's `Deployment policy` layer is the authority plane's: nothing in a policy grants, it says what the door will LOOK AT." .
368
+
369
+ appc:policyAsksPredicate a owl:ObjectProperty ;
370
+ rdfs:domain appc:VerifierPolicy ; rdfs:range appc:PredicateProgram ;
371
+ rdfs:label "policy asks predicate" .
372
+
373
+ appc:requiresNullifier a owl:DatatypeProperty ;
374
+ rdfs:domain appc:VerifierPolicy ; rdfs:range xsd:boolean ;
375
+ rdfs:label "requires nullifier" .
376
+
377
+ appc:acceptsNullifierGrade a owl:ObjectProperty ;
378
+ rdfs:domain appc:VerifierPolicy ; rdfs:range skos:Concept ;
379
+ rdfs:label "accepts nullifier grade" ;
380
+ rdfs:comment "The lowest grade accepted (appc:nullifierGradeScheme)." .
381
+
382
+ appc:nullifierWindowSeconds a owl:DatatypeProperty ;
383
+ rdfs:domain appc:VerifierPolicy ; rdfs:range xsd:integer ;
384
+ rdfs:label "nullifier window seconds" ;
385
+ rdfs:comment "One visit per audience PER WINDOW: the store forgets a value after it (epoch-scoped persistence), and the store is keyed by the window too, so a door that changes its rule starts a fresh count. Absent means once, for as long as the door remembers." .
386
+
387
+ appc:requiresStatus a owl:DatatypeProperty ;
388
+ rdfs:domain appc:VerifierPolicy ; rdfs:range xsd:boolean ;
389
+ rdfs:label "requires status" .
390
+
391
+ appc:statusMaxAgeSeconds a owl:DatatypeProperty ;
392
+ rdfs:domain appc:VerifierPolicy ; rdfs:range xsd:integer ;
393
+ rdfs:label "status max age seconds" ;
394
+ rdfs:comment "How old the anchored sequence a status is verified against may be. Older is refused, not re-fetched." .
395
+
396
+ appc:trustsIssuerFacet a owl:ObjectProperty ;
397
+ rdfs:domain appc:VerifierPolicy ; rdfs:range appc:IssuerKeyFacet ;
398
+ rdfs:label "trusts issuer facet" ;
399
+ rdfs:comment "A facet the verifier will resolve a presentation's key id against — listed in a register and re-verified on the issuer's chain at every verification. Listing is not trust: the chain is." .
400
+
401
+ appc:verifierPlacement a owl:ObjectProperty ;
402
+ rdfs:range skos:Concept ;
403
+ rdfs:label "verifier placement" ;
404
+ rdfs:comment "Where the proof is verified (appc:verifierPlacementScheme): `node` when the verifying keys do not fit the edge runtime, `worker` when they do. On the policy as a declaration and on the evidence as a fact; a receipt that cannot say where a proof was checked is not a receipt." .
405
+
406
+ appc:PredicateAdmissionEvidence a owl:Class ;
407
+ rdfs:subClassOf prov:Entity ;
408
+ rdfs:label "PredicateAdmissionEvidence" ;
409
+ rdfs:comment "THE PREDICATE HELD, AS WHAT A DOOR KEPT: the facet the proof verified under, the predicate program's digest, the nullifier's grade, the status sequence read from neutral ground, where the proof was verified — beside the admission decision, contributed by the door's `binding-credential-presentation` stage. The `predicate` proof grade of spec 442 §7.2. EVIDENCE, NEVER AUTHORITY (ADR-0056/0057): it says a credential satisfied the door's question; the estate's own mandate still governs every act the visitor asks for. No claim value, no person; the acting account is the pairwise one." .
410
+
411
+ appc:evidenceFacet a owl:ObjectProperty ;
412
+ rdfs:domain appc:PredicateAdmissionEvidence ; rdfs:range appc:IssuerKeyFacet ;
413
+ rdfs:label "evidence facet" .
414
+
415
+ appc:evidencePredicateDigest a owl:DatatypeProperty ;
416
+ rdfs:domain appc:PredicateAdmissionEvidence ; rdfs:range xsd:string ;
417
+ rdfs:label "evidence predicate digest" ;
418
+ rdfs:comment "The DOOR'S own digest of the program it asked — computed from its request, never read from the presentation." .
419
+
420
+ appc:evidenceNullifierGrade a owl:ObjectProperty ;
421
+ rdfs:domain appc:PredicateAdmissionEvidence ; rdfs:range skos:Concept ;
422
+ rdfs:label "evidence nullifier grade" .
423
+
424
+ appc:evidenceStatusSequence a owl:DatatypeProperty ;
425
+ rdfs:domain appc:PredicateAdmissionEvidence ; rdfs:range xsd:integer ;
426
+ rdfs:label "evidence status sequence" .
427
+
428
+ appc:evidencedIn a owl:ObjectProperty ;
429
+ rdfs:domain appc:PredicateAdmissionEvidence ; rdfs:range apix:AdmissionReceipt ;
430
+ rdfs:label "evidenced in" ;
431
+ rdfs:comment "The admission receipt the evidence sits beside. Admission is not authorization (ADR-0043)." .
432
+
433
+ appc:proofGrade a owl:ObjectProperty ;
434
+ rdfs:range skos:Concept ;
435
+ rdfs:label "proof grade" ;
436
+ rdfs:comment "Which kind of proof a visitor presented at a door (appc:proofGradeScheme, spec 442 §7.2): `identity` (the agent as itself), `standing` (a leaf of another estate's authority projection), `predicate` (this module). A door says which grades it accepts; a grade is never a rank." .
@@ -150,6 +150,24 @@
150
150
  "steward": "richardpedersen3@gmail.com",
151
151
  "publishedAt": "2026-10-15",
152
152
  "note": "spec 305 W2 / zkID alignment §4 (Z3): `apest:projectionSet` gains `live-credential` — a credential issuer's live set, anchored as the issuer's own row on EstateProjectionRegistry (first root slot, charterHash = the issuer tag). Comment-only T-box change; no class or property added or removed."
153
+ },
154
+ {
155
+ "manifestDigest": "0xdf7e54bdb37e5e0a299abb001c4e9ec41430f875c37f41f6cfde69353951f9fb",
156
+ "steward": "richardpedersen3@gmail.com",
157
+ "publishedAt": "2026-10-15",
158
+ "note": "Anonymous credentials — tbox/privacy-credential.ttl (appc:, 0.1.0), specs 304 / 305 / 442 §7.2 / 443 W5 and the zkID alignment waves Z1–Z4 as live at ap-federation's door. New classes: IssuerKeyFacet (anchoredBy an attestation; subject an org or service, never a person) · IssuerRow (the issuer's tagged live-credential root on neutral ground; its leaves are apest:ProjectionSubmission in the live-credential set; revocation = retire + re-anchor) · AnonymousCredential (⊑ apvc:VerifiableCredential; issuedUnder a facet, boundToDeviceKey) · DeviceKey (custodied; signs only under a mandate) · PairwiseAccount (what a verifier sees; NO property to the person, on purpose) · ProofRequest / PredicateProgram / Predicate (the verifier's own question, digested) · PrivatePresentation (answers · presentedUnder · provesPredicate · carriesNullifier · carriesStatus · madeUnderMandate · presents — the last three the holder's record only) · Nullifier (graded: asserted < in-circuit) · CredentialStatusPresentation (statusOf an IssuerRow at a sequence the verifier READ) · PresentationMandate (⊑ apdel:Delegation; audiences · predicate digests · facets · maxPresentations) · PresentationRelease (⊑ prov:Activity; one judgement per device-key signature) · VerifierPolicy (what a door asks and accepts, incl. nullifierWindowSeconds and verifierPlacement) · PredicateAdmissionEvidence (the predicate held, beside an apix:AdmissionReceipt; evidence, never authority). Codelists: presentationSuite, issuerKeySuite, nullifierGrade, predicateOp, verifierPlacement, proofGrade (identity · standing · predicate). Doctrine: proof is evidence, the mandate is authority, the receipt binds the two; no claim value and no link to the person anywhere in the vocabulary."
159
+ },
160
+ {
161
+ "manifestDigest": "0xf5494ddf4f9001f02919cc56d6ab6dd71d4e5a1b5b7efcaa68031f5d21680881",
162
+ "steward": "richardpedersen3@gmail.com",
163
+ "publishedAt": "2026-10-15",
164
+ "note": "apvc: reconciled — five T-box modules (agreement, attestation, fulfillment, payment, privacy-credential) and mappings/spine-standards.ttl bound the prefix to /ns/credential# (apcr's namespace, the CONTROL credentials) while NS.apvc, context.jsonld and the collaboration crosswalk said /ns/verifiable-credential#; and no module declared apvc:VerifiableCredential at all. Now one IRI (verifiable-credential#) everywhere and the class declared once in attestation.ttl (⊑ prov:Entity; owl:equivalentClass w3cvc:VerifiableCredential in the mapping). Every subClassOf apvc:VerifiableCredential axiom in the spine now points at a declared class. No term renamed; the prefix moved."
165
+ },
166
+ {
167
+ "manifestDigest": "0xf1f4359aba735b1cae1ac5f4439d4bd71460a9b5b6a89aed40481e80346f5730",
168
+ "steward": "richardpedersen3@gmail.com",
169
+ "publishedAt": "2026-10-15",
170
+ "note": "spec 442 §11 W0 — tbox/identity.ttl gains the four terms for a person's agent at a company's door (ap:, the core namespace; prov: prefix added): ClientKeyBinding (a Smart Agent's signed statement that one JWK may PRESENT for it at external doors under one custody epoch — a credential, not a delegation; atl:clientKeys on chain) · PairwiseSubject (what one company calls the person: HKDF over a vault secret salted by the issuer; no property to the person, as appc:PairwiseAccount) · ExternalOperation (PAP operation / ACP session / UCP checkout seen from our side — an INTENT whose digest a mandate binds; never an approval) · ExternalAccountLink (the account at one company and the credentials it left behind; a vault record the Security section lists and revokes). Properties: clientId, jwkThumbprint, jwsAlgorithm, boundUnderCustodyEpoch, bindingNotBefore/After, pairwiseIssuer, pairwiseSubjectDigest, operationAuthority, operationId, operationRevision, termsDigest, accountGrantedAt/ExpiresAt/LastUsedAt, grantedScope. Bound in vault-records.ts: identity.client-key-binding: · identity.pairwise-secret · identity.external-account-link:. Doctrine: approval is a signature, never an assertion; the person is never the client_id; protocol vocabulary (poppy.json, DPoP, Idempotency-Key) stays in ap-federation (spec 443). Nothing here is read by any verifier."
153
171
  }
154
172
  ]
155
173
  }