@openvtc/trust-tasks 0.26.18 → 0.26.19
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.
- package/CHANGELOG.md +56 -0
- package/dist/_shared/components.d.ts +113 -1
- package/dist/_shared/components.d.ts.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/rooms/owner/group/add/0.3/payload.d.ts +417 -0
- package/dist/rooms/owner/group/add/0.3/payload.d.ts.map +1 -0
- package/dist/rooms/owner/group/add/0.3/payload.js +218 -0
- package/dist/rooms/owner/group/add/0.3/payload.js.map +1 -0
- package/dist/rooms/owner/group/renew/0.2/payload.d.ts +299 -0
- package/dist/rooms/owner/group/renew/0.2/payload.d.ts.map +1 -0
- package/dist/rooms/owner/group/renew/0.2/payload.js +163 -0
- package/dist/rooms/owner/group/renew/0.2/payload.js.map +1 -0
- package/dist/vtc/directory/_shared/0.1/directory-card.d.ts +1 -1
- package/dist/vtc/directory/_shared/0.1/directory-card.d.ts.map +1 -1
- package/dist/vtc/directory/_shared/0.1/disclosure-statement.d.ts +18 -0
- package/dist/vtc/directory/_shared/0.1/disclosure-statement.d.ts.map +1 -0
- package/dist/vtc/directory/_shared/0.1/disclosure-statement.js +6 -0
- package/dist/vtc/directory/_shared/0.1/disclosure-statement.js.map +1 -0
- package/dist/vtc/directory/card/assert/0.1/payload.d.ts +4 -4
- package/dist/vtc/directory/card/assert/0.1/payload.js +2 -2
- package/dist/vtc/directory/card/assert/0.1/payload.js.map +1 -1
- package/dist/vtc/directory/card/public/0.1/payload.d.ts +348 -0
- package/dist/vtc/directory/card/public/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/directory/card/public/0.1/payload.js +197 -0
- package/dist/vtc/directory/card/public/0.1/payload.js.map +1 -0
- package/dist/vtc/directory/card/publish/0.1/payload.d.ts +384 -0
- package/dist/vtc/directory/card/publish/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/directory/card/publish/0.1/payload.js +222 -0
- package/dist/vtc/directory/card/publish/0.1/payload.js.map +1 -0
- package/dist/vtc/directory/card/show/0.1/payload.d.ts +138 -6
- package/dist/vtc/directory/card/show/0.1/payload.d.ts.map +1 -1
- package/dist/vtc/directory/card/show/0.1/payload.js +82 -2
- package/dist/vtc/directory/card/show/0.1/payload.js.map +1 -1
- package/dist/vtc/directory/card/update/0.1/payload.d.ts +138 -6
- package/dist/vtc/directory/card/update/0.1/payload.d.ts.map +1 -1
- package/dist/vtc/directory/card/update/0.1/payload.js +82 -2
- package/dist/vtc/directory/card/update/0.1/payload.js.map +1 -1
- package/dist/vtc/directory/disclosure/0.1/payload.d.ts +951 -0
- package/dist/vtc/directory/disclosure/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/directory/disclosure/0.1/payload.js +613 -0
- package/dist/vtc/directory/disclosure/0.1/payload.js.map +1 -0
- package/dist/vtc/directory/entries/list/0.1/payload.d.ts +4 -4
- package/dist/vtc/directory/entries/list/0.1/payload.js +2 -2
- package/dist/vtc/directory/entries/list/0.1/payload.js.map +1 -1
- package/dist/vtc/directory/entries/show/0.1/payload.d.ts +4 -4
- package/dist/vtc/directory/entries/show/0.1/payload.js +2 -2
- package/dist/vtc/directory/entries/show/0.1/payload.js.map +1 -1
- package/dist/vtc/directory/images/get/0.1/payload.d.ts +484 -0
- package/dist/vtc/directory/images/get/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/directory/images/get/0.1/payload.js +273 -0
- package/dist/vtc/directory/images/get/0.1/payload.js.map +1 -0
- package/dist/vtc/directory/images/upload/0.1/payload.d.ts +441 -0
- package/dist/vtc/directory/images/upload/0.1/payload.d.ts.map +1 -0
- package/dist/vtc/directory/images/upload/0.1/payload.js +262 -0
- package/dist/vtc/directory/images/upload/0.1/payload.js.map +1 -0
- package/dist/vtc/directory/introduction/0.1/payload.d.ts +2 -2
- package/dist/vtc/directory/introduction/0.1/payload.js +1 -1
- package/dist/vtc/directory/introduction/0.1/payload.js.map +1 -1
- package/dist/vtc/groups/join/0.1/payload.d.ts +4 -4
- package/dist/vtc/groups/join/0.1/payload.js +2 -2
- package/dist/vtc/groups/join/0.1/payload.js.map +1 -1
- package/dist/vtc/groups/members/add/0.1/payload.d.ts +4 -4
- package/dist/vtc/groups/members/add/0.1/payload.js +2 -2
- package/dist/vtc/groups/members/add/0.1/payload.js.map +1 -1
- package/dist/vtc/groups/members/list/0.1/payload.d.ts +4 -4
- package/dist/vtc/groups/members/list/0.1/payload.js +2 -2
- package/dist/vtc/groups/members/list/0.1/payload.js.map +1 -1
- package/dist/vtc/groups/requests/decide/0.1/payload.d.ts +4 -4
- package/dist/vtc/groups/requests/decide/0.1/payload.js +2 -2
- package/dist/vtc/groups/requests/decide/0.1/payload.js.map +1 -1
- package/dist/vtc/groups/requests/list/0.1/payload.d.ts +4 -4
- package/dist/vtc/groups/requests/list/0.1/payload.js +2 -2
- package/dist/vtc/groups/requests/list/0.1/payload.js.map +1 -1
- package/dist/vtc/join-requests/manifest/0.4/payload.d.ts +2303 -0
- package/dist/vtc/join-requests/manifest/0.4/payload.d.ts.map +1 -0
- package/dist/vtc/join-requests/manifest/0.4/payload.js +1293 -0
- package/dist/vtc/join-requests/manifest/0.4/payload.js.map +1 -0
- package/package.json +1 -1
- package/src/_shared/components.ts +113 -1
- package/src/index.ts +9 -0
- package/src/rooms/owner/group/add/0.3/payload.ts +288 -0
- package/src/rooms/owner/group/renew/0.2/payload.ts +213 -0
- package/src/vtc/directory/_shared/0.1/directory-card.ts +1 -1
- package/src/vtc/directory/_shared/0.1/disclosure-statement.ts +19 -0
- package/src/vtc/directory/card/assert/0.1/payload.ts +2 -2
- package/src/vtc/directory/card/public/0.1/payload.ts +238 -0
- package/src/vtc/directory/card/publish/0.1/payload.ts +261 -0
- package/src/vtc/directory/card/show/0.1/payload.ts +84 -4
- package/src/vtc/directory/card/update/0.1/payload.ts +84 -4
- package/src/vtc/directory/disclosure/0.1/payload.ts +645 -0
- package/src/vtc/directory/entries/list/0.1/payload.ts +2 -2
- package/src/vtc/directory/entries/show/0.1/payload.ts +2 -2
- package/src/vtc/directory/images/get/0.1/payload.ts +320 -0
- package/src/vtc/directory/images/upload/0.1/payload.ts +308 -0
- package/src/vtc/directory/introduction/0.1/payload.ts +1 -1
- package/src/vtc/groups/join/0.1/payload.ts +2 -2
- package/src/vtc/groups/members/add/0.1/payload.ts +2 -2
- package/src/vtc/groups/members/list/0.1/payload.ts +2 -2
- package/src/vtc/groups/requests/decide/0.1/payload.ts +2 -2
- package/src/vtc/groups/requests/list/0.1/payload.ts +2 -2
- package/src/vtc/join-requests/manifest/0.4/payload.ts +1490 -0
|
@@ -0,0 +1,2303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated by scripts/build-ts-bindings.mjs — DO NOT EDIT BY HAND.
|
|
3
|
+
* Source: specs/vtc/join-requests/manifest/0.4/payload.schema.json
|
|
4
|
+
*/
|
|
5
|
+
import type { Audience, ClaimType, DigestMultibase, DirectoryDisclosure, DisclosedField, Ext, ExtCritical, FieldDescription, FieldKey, FieldLabel, FieldSource, FieldType, GroupDisclosure, Introductions, Listing, NewCardDefaults, VettingDocumentation, VettingMethod } from "../../../../_shared/components.js";
|
|
6
|
+
/**
|
|
7
|
+
* An ISO 8601 duration in weeks, days, hours, minutes and seconds only (e.g. `P120D`, `P2W`, `P1DT12H`, `PT15M`). Years and months are refused: their length depends on the calendar, and an age limit that means different things on different days is not a limit.
|
|
8
|
+
*/
|
|
9
|
+
export type Duration = string;
|
|
10
|
+
/**
|
|
11
|
+
* Discover a community's join criteria before applying. The request carries nothing. Version 0.2 adds, per criterion, an optional `vetting` requirements object — how many identity-vetting statements a community needs, by which methods, from whom — and a `requirementsDigest` that names the exact version of the criterion an applicant started under. The response may also carry `branding`, how the community asks to be shown. Version 0.4 adds `directoryDisclosure`: where the community has a member directory, the statement of what it would disclose about a member and to whom, so an applicant reads it before applying.
|
|
12
|
+
*/
|
|
13
|
+
export interface VTCJoinRequestsManifestPayload {
|
|
14
|
+
ext?: Ext;
|
|
15
|
+
}
|
|
16
|
+
export interface VTCJoinRequestsManifestResponsePayload {
|
|
17
|
+
communityDid: string;
|
|
18
|
+
criteria: Criterion[];
|
|
19
|
+
/**
|
|
20
|
+
* What the community asks an applicant to tell it about themselves, as claim types — never values. Answered in persona terms: the applicant's agent discloses those attributes from the face the applicant chooses, and they arrive on vtc/join-requests/submit as `attributes`. SELF-ASSERTED: a community MUST NOT describe an answer as verified, and MUST NOT make a decision that assumes it is. Outside every criterion, so no `requirementsDigest` covers it. Absent when the community asks nothing.
|
|
21
|
+
*
|
|
22
|
+
* @maxItems 32
|
|
23
|
+
*/
|
|
24
|
+
requestedAttributes?: {
|
|
25
|
+
/**
|
|
26
|
+
* A claim-type token from the persona claim-type registry (persona/_shared/0.1/CLAIM-TYPES.md) — `name.display`, `address.country` — or an `x:` extension token.
|
|
27
|
+
*/
|
|
28
|
+
type: string;
|
|
29
|
+
/**
|
|
30
|
+
* False for an attribute the applicant may decline. A submission missing a required one is refused with vtc/join-requests/submit:attributesMissing.
|
|
31
|
+
*/
|
|
32
|
+
required?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Why the community asks, in words shown to the applicant before they disclose.
|
|
35
|
+
*/
|
|
36
|
+
purpose?: string;
|
|
37
|
+
}[];
|
|
38
|
+
branding?: CommunityBranding;
|
|
39
|
+
/**
|
|
40
|
+
* Present exactly where the community offers a member directory: the statement, generated from its configuration, of what the directory would disclose about a member and to whom — the same statement vtc/directory/disclosure returns. Outside every criterion, so no `requirementsDigest` covers it; it names itself with its own `statementDigest`.
|
|
41
|
+
*/
|
|
42
|
+
directoryDisclosure?: DirectoryDisclosure;
|
|
43
|
+
ext?: Ext;
|
|
44
|
+
}
|
|
45
|
+
export interface Criterion {
|
|
46
|
+
id: string;
|
|
47
|
+
/**
|
|
48
|
+
* Plain-language summary of the criterion, authored by the community and shown to prospective applicants. Informative: where it and `vetting` disagree, `vetting` governs.
|
|
49
|
+
*/
|
|
50
|
+
description?: string;
|
|
51
|
+
/**
|
|
52
|
+
* How the community decides a submission that meets this criterion. `automatic`: it admits the applicant without a person deciding. `review`: it refers the submission to an administrator, who decides.
|
|
53
|
+
*/
|
|
54
|
+
admission: "automatic" | "review";
|
|
55
|
+
/**
|
|
56
|
+
* The credentials an applicant must present for this criterion (opaque here). Absent: the criterion requires no credential.
|
|
57
|
+
*/
|
|
58
|
+
presentationDefinition?: {};
|
|
59
|
+
/**
|
|
60
|
+
* Whose credentials meet `presentationDefinition`: `community` (this community's own), `recognised` (this community's, or a community it recognises), or `any` (any issuer whose credential verifies). Present exactly when `presentationDefinition` is.
|
|
61
|
+
*/
|
|
62
|
+
credentialIssuers?: "any" | "community" | "recognised";
|
|
63
|
+
/**
|
|
64
|
+
* True: the criterion is met only by a submission carrying a valid, unconsumed invitation this community issued to the applicant.
|
|
65
|
+
*/
|
|
66
|
+
invitationRequired?: boolean;
|
|
67
|
+
vetting?: VettingRequirements;
|
|
68
|
+
/**
|
|
69
|
+
* Digest over the RFC 8785 (JCS) canonicalization of this criterion object with the `requirementsDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Names one version of the criterion: an applicant records it when starting an application and echoes it to vetters and at submission.
|
|
70
|
+
*/
|
|
71
|
+
requirementsDigest: DigestMultibase;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* What identity-vetting evidence a criterion needs, beyond what a presentation-definition can express: distinct eligible vetters, per-method floors, independence caps. Every number is the community's own policy. This schema supplies no defaults — an absent optional member means the community imposes no constraint of that kind, never that some protocol value applies. Deliberately open: a consumer MUST ignore members it does not recognise, so a community publishing a newer shape does not make an older client unable to read the rest. Durations: `maxStatementAge` — a statement older than this at decision time does not count (absent: no limit beyond the statement's own validity); `decisionSla` — how long after submission the community undertakes to decide, including on a referred application; `requirementsGrace` — how long an application started under an earlier `requirementsDigest` is still evaluated under that version.
|
|
75
|
+
*/
|
|
76
|
+
export interface VettingRequirements {
|
|
77
|
+
/**
|
|
78
|
+
* Version of this requirements object's shape. `0.1` for the members defined here.
|
|
79
|
+
*/
|
|
80
|
+
version: string;
|
|
81
|
+
/**
|
|
82
|
+
* The predicate IRI a counted vetting statement carries in `credentialSubject.predicate` — `https://registry.trustoverip.org/dtg/vsc/vetted/1`, the DTG VSC registry's identity-vetting predicate, or a predicate in a namespace the community controls — registered as one the community accepts via vtc/endorsement-types/register. A statement under any other predicate does not count.
|
|
83
|
+
*/
|
|
84
|
+
statementType: string;
|
|
85
|
+
/**
|
|
86
|
+
* How many counted statements are needed, counting each vetter once however many DIDs they hold.
|
|
87
|
+
*/
|
|
88
|
+
minStatements: number;
|
|
89
|
+
/**
|
|
90
|
+
* Per-method floors within `minStatements` — e.g. `{ "inPerson": 1 }`. Every method named MUST also be in `acceptedMethods`. Absent: no method floor.
|
|
91
|
+
*/
|
|
92
|
+
minByMethod?: {
|
|
93
|
+
[k: string]: number | undefined;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Methods whose statements count at all.
|
|
97
|
+
*
|
|
98
|
+
* @minItems 1
|
|
99
|
+
*/
|
|
100
|
+
acceptedMethods: [VettingMethod, ...VettingMethod[]];
|
|
101
|
+
/**
|
|
102
|
+
* Documentation a statement must have relied on in order to count. Absent — the expected case — means each vetter decides what documentation they accept, including none for prior acquaintance, and the community counts what they attest.
|
|
103
|
+
*
|
|
104
|
+
* @minItems 1
|
|
105
|
+
*/
|
|
106
|
+
acceptedDocumentClasses?: [VettingDocumentation, ...VettingDocumentation[]];
|
|
107
|
+
/**
|
|
108
|
+
* Claim types the applicant's Vetting Card must carry, which the identity commitment is computed over, and which a counted statement must list as verified. Absent: none.
|
|
109
|
+
*/
|
|
110
|
+
requiredClaims?: ClaimType[];
|
|
111
|
+
/**
|
|
112
|
+
* Claim types an applicant MAY add to the card and a vetter MAY verify. They never affect whether a statement counts.
|
|
113
|
+
*/
|
|
114
|
+
optionalClaims?: ClaimType[];
|
|
115
|
+
maxStatementAge?: Duration;
|
|
116
|
+
/**
|
|
117
|
+
* How a vetter's eligibility is established.
|
|
118
|
+
*/
|
|
119
|
+
eligibleVetters: {
|
|
120
|
+
/**
|
|
121
|
+
* The role a statement's issuer must hold, matched as the action `role:<role>` in a Verifiable Authority Credential (`AuthorityCredential`) the community issued to that issuer, whose `authority.scope` is the community's DID (see `vtc/vetting/vetters/grant/0.1`). A statement counts only if its issuer holds such a credential.
|
|
122
|
+
*/
|
|
123
|
+
role: string;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Caps on how much evidence may come from people close to the applicant. Absent: no caps.
|
|
127
|
+
*/
|
|
128
|
+
independence?: {
|
|
129
|
+
/**
|
|
130
|
+
* The most counted statements that may come from vetters declaring each relationship — e.g. `{ "family": 0 }`.
|
|
131
|
+
*/
|
|
132
|
+
maxByDeclaredRelationship?: {
|
|
133
|
+
[k: string]: number | undefined;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* When true, every counted statement must carry the same identity commitment — all vetters verified the same claimed identity. Absent: false.
|
|
137
|
+
*/
|
|
138
|
+
requireConsistentIdentityCommitment?: boolean;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Whether an invitation credential must accompany the statements at submission (`required`), may (`optional`), or plays no part (`none`). Absent: the presentation-definition alone governs.
|
|
142
|
+
*/
|
|
143
|
+
invitation?: "required" | "optional" | "none";
|
|
144
|
+
decisionSla?: Duration;
|
|
145
|
+
requirementsGrace?: Duration;
|
|
146
|
+
/**
|
|
147
|
+
* Where the community's vetting governance — including the attestation text vetters sign — is published.
|
|
148
|
+
*/
|
|
149
|
+
governanceFrameworkUrl?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Ecosystem-defined extension members per SPEC.md §4.5.1, for vetting parameters this version does not enumerate. A community publishing an admission mode the base members cannot express — the zero-knowledge parameters an applicant proves against, say — puts them under a namespace it controls, rather than waiting for a version that names them.
|
|
152
|
+
*
|
|
153
|
+
* This object is already `additionalProperties: true`, so an unknown member here has always validated. That is not the same as reaching a consumer: a generated type names the members this schema declares and drops the rest, so an undeclared member is parsed and discarded, and it is discarded again on the re-serialization `requirementsDigest` is computed over. `ext` is a declared member, so it survives both.
|
|
154
|
+
*/
|
|
155
|
+
ext?: Ext;
|
|
156
|
+
/**
|
|
157
|
+
* Namespaces of `ext` an applicant MUST understand or refuse, per SPEC.md §4.5.1.
|
|
158
|
+
*
|
|
159
|
+
* A community marks a namespace here when applying under this criterion without understanding it would mean something other than what the community requires — an applicant that ignored a hidden-vetting namespace, for instance, would submit named statements to a criterion whose whole point was that it does not receive them. An applicant that does not recognize a marked namespace stops rather than downgrading silently.
|
|
160
|
+
*
|
|
161
|
+
* Absent, which is the common case, every namespace under `ext` is advisory and ignorable.
|
|
162
|
+
*/
|
|
163
|
+
extCritical?: ExtCritical;
|
|
164
|
+
[k: string]: unknown | undefined;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* OPTIONAL. How the community asks to be shown to a prospective applicant: a name, an accent colour and a logo. Presentation only, self-asserted and unverified — `communityDid` identifies the community, never `branding`. Not part of any criterion, so not covered by a `requirementsDigest`. Every member is optional.
|
|
168
|
+
*/
|
|
169
|
+
export interface CommunityBranding {
|
|
170
|
+
/**
|
|
171
|
+
* The community's name as it asks to be shown.
|
|
172
|
+
*/
|
|
173
|
+
displayName?: string;
|
|
174
|
+
/**
|
|
175
|
+
* An sRGB colour as `#rrggbb`, compared case-insensitively. A community SHOULD write it in lower case.
|
|
176
|
+
*/
|
|
177
|
+
accentColor?: string;
|
|
178
|
+
/**
|
|
179
|
+
* An https URL of the community's logo. Fetched by the client, so an untrusted image from wherever it points.
|
|
180
|
+
*/
|
|
181
|
+
logoUrl?: string;
|
|
182
|
+
ext?: Ext;
|
|
183
|
+
}
|
|
184
|
+
/** Shared definitions this specification references, re-exported under the names it used to declare them with. */
|
|
185
|
+
export type { Audience, ClaimType, DigestMultibase, DirectoryDisclosure, DisclosedField, Ext, ExtCritical, FieldDescription, FieldKey, FieldLabel, FieldSource, FieldType, GroupDisclosure, Introductions, Listing, NewCardDefaults, VettingDocumentation, VettingMethod };
|
|
186
|
+
/** Trust Task type URI. */
|
|
187
|
+
export declare const TYPE_URI: "https://trusttasks.org/spec/vtc/join-requests/manifest/0.4";
|
|
188
|
+
/** Stable alias for this specification's request payload shape. */
|
|
189
|
+
export type Payload = VTCJoinRequestsManifestPayload;
|
|
190
|
+
/** Trust Task response type URI (request type URI + "#response"). */
|
|
191
|
+
export declare const RESPONSE_TYPE_URI: "https://trusttasks.org/spec/vtc/join-requests/manifest/0.4#response";
|
|
192
|
+
/** Stable alias for this specification's success-response payload shape. */
|
|
193
|
+
export type Response = VTCJoinRequestsManifestResponsePayload;
|
|
194
|
+
/**
|
|
195
|
+
* This specification's payload schema, as a value.
|
|
196
|
+
*
|
|
197
|
+
* SPEC.md §7.2 item 2 is performed against this. It is shipped as data
|
|
198
|
+
* rather than only as a `.json` file because TypeScript types are erased
|
|
199
|
+
* at runtime: without a schema a consumer has nothing to validate, and
|
|
200
|
+
* every REQUIRED payload member is optional in practice. Cross-file
|
|
201
|
+
* `$ref`s are already inlined, so it needs no resolver.
|
|
202
|
+
*/
|
|
203
|
+
export declare const PAYLOAD_SCHEMA: {
|
|
204
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
205
|
+
readonly $id: "https://trusttasks.org/spec/vtc/join-requests/manifest/0.4";
|
|
206
|
+
readonly title: "VTC Join-Requests Manifest — payload";
|
|
207
|
+
readonly description: "Discover a community's join criteria before applying. The request carries nothing. Version 0.2 adds, per criterion, an optional `vetting` requirements object — how many identity-vetting statements a community needs, by which methods, from whom — and a `requirementsDigest` that names the exact version of the criterion an applicant started under. The response may also carry `branding`, how the community asks to be shown. Version 0.4 adds `directoryDisclosure`: where the community has a member directory, the statement of what it would disclose about a member and to whom, so an applicant reads it before applying.";
|
|
208
|
+
readonly type: "object";
|
|
209
|
+
readonly additionalProperties: false;
|
|
210
|
+
readonly properties: {
|
|
211
|
+
readonly ext: {
|
|
212
|
+
readonly $ref: "#/$defs/Ext";
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
readonly $defs: {
|
|
216
|
+
readonly Duration: {
|
|
217
|
+
readonly title: "Duration";
|
|
218
|
+
readonly type: "string";
|
|
219
|
+
readonly maxLength: 32;
|
|
220
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
221
|
+
readonly description: "An ISO 8601 duration in weeks, days, hours, minutes and seconds only (e.g. `P120D`, `P2W`, `P1DT12H`, `PT15M`). Years and months are refused: their length depends on the calendar, and an age limit that means different things on different days is not a limit.";
|
|
222
|
+
};
|
|
223
|
+
readonly Criterion: {
|
|
224
|
+
readonly title: "Criterion";
|
|
225
|
+
readonly type: "object";
|
|
226
|
+
readonly additionalProperties: false;
|
|
227
|
+
readonly required: readonly ["id", "admission", "requirementsDigest"];
|
|
228
|
+
readonly properties: {
|
|
229
|
+
readonly id: {
|
|
230
|
+
readonly type: "string";
|
|
231
|
+
readonly minLength: 1;
|
|
232
|
+
readonly maxLength: 128;
|
|
233
|
+
};
|
|
234
|
+
readonly description: {
|
|
235
|
+
readonly type: "string";
|
|
236
|
+
readonly maxLength: 1024;
|
|
237
|
+
readonly description: "Plain-language summary of the criterion, authored by the community and shown to prospective applicants. Informative: where it and `vetting` disagree, `vetting` governs.";
|
|
238
|
+
};
|
|
239
|
+
readonly admission: {
|
|
240
|
+
readonly type: "string";
|
|
241
|
+
readonly enum: readonly ["automatic", "review"];
|
|
242
|
+
readonly description: "How the community decides a submission that meets this criterion. `automatic`: it admits the applicant without a person deciding. `review`: it refers the submission to an administrator, who decides.";
|
|
243
|
+
};
|
|
244
|
+
readonly presentationDefinition: {
|
|
245
|
+
readonly type: "object";
|
|
246
|
+
readonly description: "The credentials an applicant must present for this criterion (opaque here). Absent: the criterion requires no credential.";
|
|
247
|
+
};
|
|
248
|
+
readonly credentialIssuers: {
|
|
249
|
+
readonly type: "string";
|
|
250
|
+
readonly enum: readonly ["any", "community", "recognised"];
|
|
251
|
+
readonly description: "Whose credentials meet `presentationDefinition`: `community` (this community's own), `recognised` (this community's, or a community it recognises), or `any` (any issuer whose credential verifies). Present exactly when `presentationDefinition` is.";
|
|
252
|
+
};
|
|
253
|
+
readonly invitationRequired: {
|
|
254
|
+
readonly type: "boolean";
|
|
255
|
+
readonly description: "True: the criterion is met only by a submission carrying a valid, unconsumed invitation this community issued to the applicant.";
|
|
256
|
+
};
|
|
257
|
+
readonly vetting: {
|
|
258
|
+
readonly $ref: "#/$defs/VettingRequirements";
|
|
259
|
+
};
|
|
260
|
+
readonly requirementsDigest: {
|
|
261
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
262
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this criterion object with the `requirementsDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Names one version of the criterion: an applicant records it when starting an application and echoes it to vetters and at submission.";
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
readonly dependentRequired: {
|
|
266
|
+
readonly presentationDefinition: readonly ["credentialIssuers"];
|
|
267
|
+
readonly credentialIssuers: readonly ["presentationDefinition"];
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
readonly VettingRequirements: {
|
|
271
|
+
readonly title: "VettingRequirements";
|
|
272
|
+
readonly type: "object";
|
|
273
|
+
readonly additionalProperties: true;
|
|
274
|
+
readonly required: readonly ["version", "statementType", "minStatements", "acceptedMethods", "eligibleVetters"];
|
|
275
|
+
readonly description: "What identity-vetting evidence a criterion needs, beyond what a presentation-definition can express: distinct eligible vetters, per-method floors, independence caps. Every number is the community's own policy. This schema supplies no defaults — an absent optional member means the community imposes no constraint of that kind, never that some protocol value applies. Deliberately open: a consumer MUST ignore members it does not recognise, so a community publishing a newer shape does not make an older client unable to read the rest. Durations: `maxStatementAge` — a statement older than this at decision time does not count (absent: no limit beyond the statement's own validity); `decisionSla` — how long after submission the community undertakes to decide, including on a referred application; `requirementsGrace` — how long an application started under an earlier `requirementsDigest` is still evaluated under that version.";
|
|
276
|
+
readonly properties: {
|
|
277
|
+
readonly version: {
|
|
278
|
+
readonly type: "string";
|
|
279
|
+
readonly pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$";
|
|
280
|
+
readonly description: "Version of this requirements object's shape. `0.1` for the members defined here.";
|
|
281
|
+
};
|
|
282
|
+
readonly statementType: {
|
|
283
|
+
readonly type: "string";
|
|
284
|
+
readonly format: "uri";
|
|
285
|
+
readonly minLength: 1;
|
|
286
|
+
readonly maxLength: 512;
|
|
287
|
+
readonly description: "The predicate IRI a counted vetting statement carries in `credentialSubject.predicate` — `https://registry.trustoverip.org/dtg/vsc/vetted/1`, the DTG VSC registry's identity-vetting predicate, or a predicate in a namespace the community controls — registered as one the community accepts via vtc/endorsement-types/register. A statement under any other predicate does not count.";
|
|
288
|
+
};
|
|
289
|
+
readonly minStatements: {
|
|
290
|
+
readonly type: "integer";
|
|
291
|
+
readonly minimum: 1;
|
|
292
|
+
readonly description: "How many counted statements are needed, counting each vetter once however many DIDs they hold.";
|
|
293
|
+
};
|
|
294
|
+
readonly minByMethod: {
|
|
295
|
+
readonly type: "object";
|
|
296
|
+
readonly propertyNames: {
|
|
297
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
298
|
+
};
|
|
299
|
+
readonly additionalProperties: {
|
|
300
|
+
readonly type: "integer";
|
|
301
|
+
readonly minimum: 0;
|
|
302
|
+
};
|
|
303
|
+
readonly description: "Per-method floors within `minStatements` — e.g. `{ \"inPerson\": 1 }`. Every method named MUST also be in `acceptedMethods`. Absent: no method floor.";
|
|
304
|
+
};
|
|
305
|
+
readonly acceptedMethods: {
|
|
306
|
+
readonly type: "array";
|
|
307
|
+
readonly minItems: 1;
|
|
308
|
+
readonly uniqueItems: true;
|
|
309
|
+
readonly items: {
|
|
310
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
311
|
+
};
|
|
312
|
+
readonly description: "Methods whose statements count at all.";
|
|
313
|
+
};
|
|
314
|
+
readonly acceptedDocumentClasses: {
|
|
315
|
+
readonly type: "array";
|
|
316
|
+
readonly minItems: 1;
|
|
317
|
+
readonly uniqueItems: true;
|
|
318
|
+
readonly items: {
|
|
319
|
+
readonly $ref: "#/$defs/VettingDocumentation";
|
|
320
|
+
};
|
|
321
|
+
readonly description: "Documentation a statement must have relied on in order to count. Absent — the expected case — means each vetter decides what documentation they accept, including none for prior acquaintance, and the community counts what they attest.";
|
|
322
|
+
};
|
|
323
|
+
readonly requiredClaims: {
|
|
324
|
+
readonly type: "array";
|
|
325
|
+
readonly uniqueItems: true;
|
|
326
|
+
readonly items: {
|
|
327
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
328
|
+
};
|
|
329
|
+
readonly description: "Claim types the applicant's Vetting Card must carry, which the identity commitment is computed over, and which a counted statement must list as verified. Absent: none.";
|
|
330
|
+
};
|
|
331
|
+
readonly optionalClaims: {
|
|
332
|
+
readonly type: "array";
|
|
333
|
+
readonly uniqueItems: true;
|
|
334
|
+
readonly items: {
|
|
335
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
336
|
+
};
|
|
337
|
+
readonly description: "Claim types an applicant MAY add to the card and a vetter MAY verify. They never affect whether a statement counts.";
|
|
338
|
+
};
|
|
339
|
+
readonly maxStatementAge: {
|
|
340
|
+
readonly $ref: "#/$defs/Duration";
|
|
341
|
+
};
|
|
342
|
+
readonly eligibleVetters: {
|
|
343
|
+
readonly type: "object";
|
|
344
|
+
readonly additionalProperties: false;
|
|
345
|
+
readonly required: readonly ["role"];
|
|
346
|
+
readonly properties: {
|
|
347
|
+
readonly role: {
|
|
348
|
+
readonly type: "string";
|
|
349
|
+
readonly minLength: 1;
|
|
350
|
+
readonly maxLength: 128;
|
|
351
|
+
readonly pattern: "^[a-zA-Z][a-zA-Z0-9_-]*$";
|
|
352
|
+
readonly description: "The role a statement's issuer must hold, matched as the action `role:<role>` in a Verifiable Authority Credential (`AuthorityCredential`) the community issued to that issuer, whose `authority.scope` is the community's DID (see `vtc/vetting/vetters/grant/0.1`). A statement counts only if its issuer holds such a credential.";
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
readonly description: "How a vetter's eligibility is established.";
|
|
356
|
+
};
|
|
357
|
+
readonly independence: {
|
|
358
|
+
readonly type: "object";
|
|
359
|
+
readonly additionalProperties: false;
|
|
360
|
+
readonly properties: {
|
|
361
|
+
readonly maxByDeclaredRelationship: {
|
|
362
|
+
readonly type: "object";
|
|
363
|
+
readonly propertyNames: {
|
|
364
|
+
readonly $ref: "#/$defs/VettingRelationship";
|
|
365
|
+
};
|
|
366
|
+
readonly additionalProperties: {
|
|
367
|
+
readonly type: "integer";
|
|
368
|
+
readonly minimum: 0;
|
|
369
|
+
};
|
|
370
|
+
readonly description: "The most counted statements that may come from vetters declaring each relationship — e.g. `{ \"family\": 0 }`.";
|
|
371
|
+
};
|
|
372
|
+
readonly requireConsistentIdentityCommitment: {
|
|
373
|
+
readonly type: "boolean";
|
|
374
|
+
readonly description: "When true, every counted statement must carry the same identity commitment — all vetters verified the same claimed identity. Absent: false.";
|
|
375
|
+
};
|
|
376
|
+
};
|
|
377
|
+
readonly description: "Caps on how much evidence may come from people close to the applicant. Absent: no caps.";
|
|
378
|
+
};
|
|
379
|
+
readonly invitation: {
|
|
380
|
+
readonly type: "string";
|
|
381
|
+
readonly enum: readonly ["required", "optional", "none"];
|
|
382
|
+
readonly description: "Whether an invitation credential must accompany the statements at submission (`required`), may (`optional`), or plays no part (`none`). Absent: the presentation-definition alone governs.";
|
|
383
|
+
};
|
|
384
|
+
readonly decisionSla: {
|
|
385
|
+
readonly $ref: "#/$defs/Duration";
|
|
386
|
+
};
|
|
387
|
+
readonly requirementsGrace: {
|
|
388
|
+
readonly $ref: "#/$defs/Duration";
|
|
389
|
+
};
|
|
390
|
+
readonly governanceFrameworkUrl: {
|
|
391
|
+
readonly type: "string";
|
|
392
|
+
readonly format: "uri";
|
|
393
|
+
readonly pattern: "^https://";
|
|
394
|
+
readonly maxLength: 2048;
|
|
395
|
+
readonly description: "Where the community's vetting governance — including the attestation text vetters sign — is published.";
|
|
396
|
+
};
|
|
397
|
+
readonly ext: {
|
|
398
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1, for vetting parameters this version does not enumerate. A community publishing an admission mode the base members cannot express — the zero-knowledge parameters an applicant proves against, say — puts them under a namespace it controls, rather than waiting for a version that names them.\n\nThis object is already `additionalProperties: true`, so an unknown member here has always validated. That is not the same as reaching a consumer: a generated type names the members this schema declares and drops the rest, so an undeclared member is parsed and discarded, and it is discarded again on the re-serialization `requirementsDigest` is computed over. `ext` is a declared member, so it survives both.";
|
|
399
|
+
readonly $ref: "#/$defs/Ext";
|
|
400
|
+
};
|
|
401
|
+
readonly extCritical: {
|
|
402
|
+
readonly description: "Namespaces of `ext` an applicant MUST understand or refuse, per SPEC.md §4.5.1.\n\nA community marks a namespace here when applying under this criterion without understanding it would mean something other than what the community requires — an applicant that ignored a hidden-vetting namespace, for instance, would submit named statements to a criterion whose whole point was that it does not receive them. An applicant that does not recognize a marked namespace stops rather than downgrading silently.\n\nAbsent, which is the common case, every namespace under `ext` is advisory and ignorable.";
|
|
403
|
+
readonly $ref: "#/$defs/ExtCritical";
|
|
404
|
+
};
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
readonly CommunityBranding: {
|
|
408
|
+
readonly title: "CommunityBranding";
|
|
409
|
+
readonly type: "object";
|
|
410
|
+
readonly additionalProperties: false;
|
|
411
|
+
readonly description: "OPTIONAL. How the community asks to be shown to a prospective applicant: a name, an accent colour and a logo. Presentation only, self-asserted and unverified — `communityDid` identifies the community, never `branding`. Not part of any criterion, so not covered by a `requirementsDigest`. Every member is optional.";
|
|
412
|
+
readonly properties: {
|
|
413
|
+
readonly displayName: {
|
|
414
|
+
readonly type: "string";
|
|
415
|
+
readonly minLength: 1;
|
|
416
|
+
readonly maxLength: 128;
|
|
417
|
+
readonly description: "The community's name as it asks to be shown.";
|
|
418
|
+
};
|
|
419
|
+
readonly accentColor: {
|
|
420
|
+
readonly type: "string";
|
|
421
|
+
readonly pattern: "^#[0-9a-fA-F]{6}$";
|
|
422
|
+
readonly description: "An sRGB colour as `#rrggbb`, compared case-insensitively. A community SHOULD write it in lower case.";
|
|
423
|
+
};
|
|
424
|
+
readonly logoUrl: {
|
|
425
|
+
readonly type: "string";
|
|
426
|
+
readonly format: "uri";
|
|
427
|
+
readonly pattern: "^https://";
|
|
428
|
+
readonly maxLength: 2048;
|
|
429
|
+
readonly description: "An https URL of the community's logo. Fetched by the client, so an untrusted image from wherever it points.";
|
|
430
|
+
};
|
|
431
|
+
readonly ext: {
|
|
432
|
+
readonly $ref: "#/$defs/Ext";
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
};
|
|
436
|
+
readonly Response: {
|
|
437
|
+
readonly $anchor: "response";
|
|
438
|
+
readonly title: "VTC Join-Requests Manifest — response payload";
|
|
439
|
+
readonly type: "object";
|
|
440
|
+
readonly additionalProperties: false;
|
|
441
|
+
readonly required: readonly ["communityDid", "criteria"];
|
|
442
|
+
readonly properties: {
|
|
443
|
+
readonly communityDid: {
|
|
444
|
+
readonly type: "string";
|
|
445
|
+
readonly pattern: "^did:";
|
|
446
|
+
};
|
|
447
|
+
readonly criteria: {
|
|
448
|
+
readonly type: "array";
|
|
449
|
+
readonly items: {
|
|
450
|
+
readonly $ref: "#/$defs/Criterion";
|
|
451
|
+
};
|
|
452
|
+
};
|
|
453
|
+
readonly requestedAttributes: {
|
|
454
|
+
readonly type: "array";
|
|
455
|
+
readonly maxItems: 32;
|
|
456
|
+
readonly description: "What the community asks an applicant to tell it about themselves, as claim types — never values. Answered in persona terms: the applicant's agent discloses those attributes from the face the applicant chooses, and they arrive on vtc/join-requests/submit as `attributes`. SELF-ASSERTED: a community MUST NOT describe an answer as verified, and MUST NOT make a decision that assumes it is. Outside every criterion, so no `requirementsDigest` covers it. Absent when the community asks nothing.";
|
|
457
|
+
readonly items: {
|
|
458
|
+
readonly type: "object";
|
|
459
|
+
readonly additionalProperties: false;
|
|
460
|
+
readonly required: readonly ["type"];
|
|
461
|
+
readonly properties: {
|
|
462
|
+
readonly type: {
|
|
463
|
+
readonly type: "string";
|
|
464
|
+
readonly minLength: 1;
|
|
465
|
+
readonly maxLength: 128;
|
|
466
|
+
readonly pattern: "^(x:)?[a-z][A-Za-z0-9]*(\\.[a-z][A-Za-z0-9]*)*$";
|
|
467
|
+
readonly description: "A claim-type token from the persona claim-type registry (persona/_shared/0.1/CLAIM-TYPES.md) — `name.display`, `address.country` — or an `x:` extension token.";
|
|
468
|
+
};
|
|
469
|
+
readonly required: {
|
|
470
|
+
readonly type: "boolean";
|
|
471
|
+
readonly default: true;
|
|
472
|
+
readonly description: "False for an attribute the applicant may decline. A submission missing a required one is refused with vtc/join-requests/submit:attributesMissing.";
|
|
473
|
+
};
|
|
474
|
+
readonly purpose: {
|
|
475
|
+
readonly type: "string";
|
|
476
|
+
readonly maxLength: 256;
|
|
477
|
+
readonly description: "Why the community asks, in words shown to the applicant before they disclose.";
|
|
478
|
+
};
|
|
479
|
+
};
|
|
480
|
+
};
|
|
481
|
+
};
|
|
482
|
+
readonly branding: {
|
|
483
|
+
readonly $ref: "#/$defs/CommunityBranding";
|
|
484
|
+
};
|
|
485
|
+
readonly directoryDisclosure: {
|
|
486
|
+
readonly $ref: "#/$defs/DirectoryDisclosure";
|
|
487
|
+
readonly description: "Present exactly where the community offers a member directory: the statement, generated from its configuration, of what the directory would disclose about a member and to whom — the same statement vtc/directory/disclosure returns. Outside every criterion, so no `requirementsDigest` covers it; it names itself with its own `statementDigest`.";
|
|
488
|
+
};
|
|
489
|
+
readonly ext: {
|
|
490
|
+
readonly $ref: "#/$defs/Ext";
|
|
491
|
+
};
|
|
492
|
+
};
|
|
493
|
+
};
|
|
494
|
+
readonly Ext: {
|
|
495
|
+
readonly title: "Ext";
|
|
496
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
497
|
+
readonly type: "object";
|
|
498
|
+
readonly minProperties: 1;
|
|
499
|
+
readonly additionalProperties: true;
|
|
500
|
+
readonly propertyNames: {
|
|
501
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
502
|
+
};
|
|
503
|
+
};
|
|
504
|
+
readonly DirectoryDisclosure: {
|
|
505
|
+
readonly title: "DirectoryDisclosure";
|
|
506
|
+
readonly description: "The statement itself. Every member is generated from the community's configuration when the statement is read. `statementDigest` names this exact statement, so an applicant can record which one it was shown.";
|
|
507
|
+
readonly type: "object";
|
|
508
|
+
readonly additionalProperties: false;
|
|
509
|
+
readonly required: readonly ["fields", "newCard", "membershipIdentifiers", "adminNotes", "externalCards", "statementDigest"];
|
|
510
|
+
readonly properties: {
|
|
511
|
+
readonly fields: {
|
|
512
|
+
readonly type: "array";
|
|
513
|
+
readonly maxItems: 128;
|
|
514
|
+
readonly items: {
|
|
515
|
+
readonly $ref: "#/$defs/DisclosedField";
|
|
516
|
+
};
|
|
517
|
+
readonly description: "Every active field, base and community-defined, in display order. A base field the community has disabled is absent, which is how a reader learns it is not collected.";
|
|
518
|
+
};
|
|
519
|
+
readonly newCard: {
|
|
520
|
+
readonly $ref: "#/$defs/NewCardDefaults";
|
|
521
|
+
};
|
|
522
|
+
readonly membershipIdentifiers: {
|
|
523
|
+
readonly $ref: "#/$defs/Audience";
|
|
524
|
+
readonly description: "The widest audience a member's membership identifier — the DID they joined with — can reach through the directory: the ceiling of the base field `did`, or `admins` where that field is disabled. `members` or `public` means a member may choose to show it that widely; a new card never shows it beyond `admins` (VTI-DIR-042). Administrators always see it.";
|
|
525
|
+
};
|
|
526
|
+
readonly adminNotes: {
|
|
527
|
+
readonly type: "boolean";
|
|
528
|
+
readonly description: "Whether administrators keep notes about members. Notes are never on a card and never reach another member; a member may ask for the notes about them.";
|
|
529
|
+
};
|
|
530
|
+
readonly groups: {
|
|
531
|
+
readonly $ref: "#/$defs/GroupDisclosure";
|
|
532
|
+
};
|
|
533
|
+
readonly externalCards: {
|
|
534
|
+
readonly type: "boolean";
|
|
535
|
+
readonly description: "Whether a member may publish a card beyond the community: their `public` values, signed by them, offered through the community's trust registry. Always the member's own choice, and off on a new card. False where the community cannot publish external cards.";
|
|
536
|
+
};
|
|
537
|
+
readonly statementDigest: {
|
|
538
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
539
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this statement with the `statementDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Changes exactly when what the statement says changes.";
|
|
540
|
+
};
|
|
541
|
+
readonly ext: {
|
|
542
|
+
readonly $ref: "#/$defs/Ext";
|
|
543
|
+
};
|
|
544
|
+
};
|
|
545
|
+
};
|
|
546
|
+
readonly GroupDisclosure: {
|
|
547
|
+
readonly title: "GroupDisclosure";
|
|
548
|
+
readonly description: "Present when the community has groups. A member of a group holds a credential, issued by the group's own identifier, that evidences their membership, and can present it outside the community — which is why an applicant is told.";
|
|
549
|
+
readonly type: "object";
|
|
550
|
+
readonly additionalProperties: false;
|
|
551
|
+
readonly required: readonly ["credentialValidity"];
|
|
552
|
+
readonly properties: {
|
|
553
|
+
readonly credentialValidity: {
|
|
554
|
+
readonly type: "string";
|
|
555
|
+
readonly maxLength: 32;
|
|
556
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
557
|
+
readonly description: "How long each group membership credential is valid for, as an ISO 8601 duration in weeks, days, hours, minutes and seconds (`P30D`). It is renewed while the member stays in the group, and a credential already issued stays valid until it expires even after its holder leaves.";
|
|
558
|
+
};
|
|
559
|
+
};
|
|
560
|
+
};
|
|
561
|
+
readonly NewCardDefaults: {
|
|
562
|
+
readonly title: "NewCardDefaults";
|
|
563
|
+
readonly description: "The discoverability a card has when the community creates it, before its member chooses. A new card is never published beyond the community (VTI-DIR-042), so there is no member for that here: `externalCards` says whether the member may turn it on.";
|
|
564
|
+
readonly type: "object";
|
|
565
|
+
readonly additionalProperties: false;
|
|
566
|
+
readonly required: readonly ["listing", "search"];
|
|
567
|
+
readonly properties: {
|
|
568
|
+
readonly listing: {
|
|
569
|
+
readonly $ref: "#/$defs/Listing";
|
|
570
|
+
readonly description: "The listing a new card starts with: the community's `defaultListing` (vtc/directory/fields/list). Every member may always choose `hidden`.";
|
|
571
|
+
};
|
|
572
|
+
readonly search: {
|
|
573
|
+
readonly type: "string";
|
|
574
|
+
readonly enum: readonly ["byName", "exactNickname", "off"];
|
|
575
|
+
readonly description: "What a member's search may match, as the card's `discoverability.search`.";
|
|
576
|
+
};
|
|
577
|
+
readonly introductions: {
|
|
578
|
+
readonly $ref: "#/$defs/Introductions";
|
|
579
|
+
readonly description: "From whom a new card accepts introductions. Absent where the community does not deliver introductions.";
|
|
580
|
+
};
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
readonly Introductions: {
|
|
584
|
+
readonly title: "Introductions";
|
|
585
|
+
readonly description: "Who may ask the community to introduce them to this member. `anyone`: any active member who can find the entry. `groups`: only members who share a community group with them. `connections`: only members holding an attributed, in-force verified relationship with them. `off`: nobody. A refused introduction is never reported to its sender.";
|
|
586
|
+
readonly type: "string";
|
|
587
|
+
readonly enum: readonly ["anyone", "groups", "connections", "off"];
|
|
588
|
+
};
|
|
589
|
+
readonly Listing: {
|
|
590
|
+
readonly title: "Listing";
|
|
591
|
+
readonly description: "Whether members can find the entry. `listed`: it appears when members browse. `findable`: it does not appear when browsing, but a search that matches it under `search` returns it. `hidden`: no member finds it by browsing or searching; administrators still see it, and members who share a group that shows its members see it in that group's member list.";
|
|
592
|
+
readonly type: "string";
|
|
593
|
+
readonly enum: readonly ["listed", "findable", "hidden"];
|
|
594
|
+
};
|
|
595
|
+
readonly DisclosedField: {
|
|
596
|
+
readonly title: "DisclosedField";
|
|
597
|
+
readonly description: "One active field of the community's directory, as an applicant needs to see it: what it is, who writes its value, the widest audience it may ever reach and the audience a new card gives it. Disabled and retired fields are not listed: no projection shows them.";
|
|
598
|
+
readonly type: "object";
|
|
599
|
+
readonly additionalProperties: false;
|
|
600
|
+
readonly required: readonly ["key", "label", "type", "source", "ceiling", "defaultVisibility", "searchable"];
|
|
601
|
+
readonly properties: {
|
|
602
|
+
readonly key: {
|
|
603
|
+
readonly $ref: "#/$defs/FieldKey";
|
|
604
|
+
};
|
|
605
|
+
readonly label: {
|
|
606
|
+
readonly $ref: "#/$defs/FieldLabel";
|
|
607
|
+
};
|
|
608
|
+
readonly description: {
|
|
609
|
+
readonly $ref: "#/$defs/FieldDescription";
|
|
610
|
+
};
|
|
611
|
+
readonly type: {
|
|
612
|
+
readonly $ref: "#/$defs/FieldType";
|
|
613
|
+
};
|
|
614
|
+
readonly source: {
|
|
615
|
+
readonly $ref: "#/$defs/FieldSource";
|
|
616
|
+
readonly description: "Who writes the value. `admin` and `credential` matter most to an applicant: an `admin` field holds what the community asserts about the member, which the member reads and cannot change.";
|
|
617
|
+
};
|
|
618
|
+
readonly ceiling: {
|
|
619
|
+
readonly $ref: "#/$defs/Audience";
|
|
620
|
+
readonly description: "The widest audience the field may ever reach, whatever the member chooses.";
|
|
621
|
+
};
|
|
622
|
+
readonly defaultVisibility: {
|
|
623
|
+
readonly $ref: "#/$defs/Audience";
|
|
624
|
+
readonly description: "The audience a new card gives the field until its member chooses. Never wider than `ceiling`.";
|
|
625
|
+
};
|
|
626
|
+
readonly searchable: {
|
|
627
|
+
readonly type: "boolean";
|
|
628
|
+
readonly description: "Whether a member's search may match the field, within what the searcher may see.";
|
|
629
|
+
};
|
|
630
|
+
readonly facet: {
|
|
631
|
+
readonly type: "boolean";
|
|
632
|
+
readonly description: "Whether members may filter on the field and see counts by its values. Absent: false.";
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
};
|
|
636
|
+
readonly Audience: {
|
|
637
|
+
readonly title: "Audience";
|
|
638
|
+
readonly description: "Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\n\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.";
|
|
639
|
+
readonly type: "string";
|
|
640
|
+
readonly enum: readonly ["admins", "groups", "connections", "members", "public"];
|
|
641
|
+
};
|
|
642
|
+
readonly FieldSource: {
|
|
643
|
+
readonly title: "FieldSource";
|
|
644
|
+
readonly description: "Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.";
|
|
645
|
+
readonly type: "string";
|
|
646
|
+
readonly enum: readonly ["member", "admin", "credential", "derived"];
|
|
647
|
+
};
|
|
648
|
+
readonly FieldType: {
|
|
649
|
+
readonly title: "FieldType";
|
|
650
|
+
readonly description: "The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.";
|
|
651
|
+
readonly type: "string";
|
|
652
|
+
readonly enum: readonly ["text", "longText", "url", "email", "phone", "enum", "multiEnum", "date", "country", "image", "did", "claim"];
|
|
653
|
+
};
|
|
654
|
+
readonly FieldDescription: {
|
|
655
|
+
readonly title: "FieldDescription";
|
|
656
|
+
readonly type: "string";
|
|
657
|
+
readonly minLength: 1;
|
|
658
|
+
readonly maxLength: 280;
|
|
659
|
+
readonly description: "Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.";
|
|
660
|
+
};
|
|
661
|
+
readonly FieldLabel: {
|
|
662
|
+
readonly title: "FieldLabel";
|
|
663
|
+
readonly type: "string";
|
|
664
|
+
readonly minLength: 1;
|
|
665
|
+
readonly maxLength: 64;
|
|
666
|
+
readonly description: "What readers see as the field's name. Plain text.";
|
|
667
|
+
};
|
|
668
|
+
readonly FieldKey: {
|
|
669
|
+
readonly title: "FieldKey";
|
|
670
|
+
readonly description: "Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.";
|
|
671
|
+
readonly type: "string";
|
|
672
|
+
readonly minLength: 1;
|
|
673
|
+
readonly maxLength: 128;
|
|
674
|
+
readonly pattern: "^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$";
|
|
675
|
+
};
|
|
676
|
+
readonly DigestMultibase: {
|
|
677
|
+
readonly title: "DigestMultibase";
|
|
678
|
+
readonly description: "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.";
|
|
679
|
+
readonly type: "string";
|
|
680
|
+
readonly minLength: 16;
|
|
681
|
+
readonly pattern: "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$";
|
|
682
|
+
readonly examples: readonly ["zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"];
|
|
683
|
+
};
|
|
684
|
+
readonly ExtCritical: {
|
|
685
|
+
readonly title: "ExtCritical";
|
|
686
|
+
readonly description: "Names the `ext` namespaces a consumer MUST understand or refuse, per SPEC.md §4.5.1.\n\nEvery entry MUST be an immediate key of the sibling `ext` object at the same level; an entry naming an absent namespace is non-conforming and the consumer rejects the document with `malformedRequest`. A consumer that does not recognize a namespace named here MUST NOT process the document as though the namespace were absent, and rejects it with `unsupportedExtension` — the exception to the rule that unrecognized namespaces are ignored.\n\nA producer marks a namespace only where the document's meaning depends on it. Marking one that merely carries a hint or an annotation turns every consumer that has not implemented it into a failure where it would otherwise have interoperated. JSON Schema cannot check either of those rules: that an entry names a present namespace is checkable only against the sibling `ext`, and whether a namespace is load-bearing is not a schema question at all. Both are consumer-side checks.";
|
|
687
|
+
readonly type: "array";
|
|
688
|
+
readonly minItems: 1;
|
|
689
|
+
readonly uniqueItems: true;
|
|
690
|
+
readonly items: {
|
|
691
|
+
readonly type: "string";
|
|
692
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
693
|
+
};
|
|
694
|
+
readonly examples: readonly [readonly ["org.openvtc.hidden-vetting"]];
|
|
695
|
+
};
|
|
696
|
+
readonly VettingRelationship: {
|
|
697
|
+
readonly title: "VettingRelationship";
|
|
698
|
+
readonly type: "string";
|
|
699
|
+
readonly enum: readonly ["none", "communityColleague", "sameEmployer", "family", "otherPersonal"];
|
|
700
|
+
readonly description: "The vetter's own declaration of how they relate to the applicant. Declared, not verified: it exists so community policy can cap how much evidence comes from people close to the applicant, and a false declaration is the vetter's attributable act.";
|
|
701
|
+
};
|
|
702
|
+
readonly ClaimType: {
|
|
703
|
+
readonly title: "ClaimType";
|
|
704
|
+
readonly description: "The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\n\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\n\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.";
|
|
705
|
+
readonly type: "string";
|
|
706
|
+
readonly minLength: 1;
|
|
707
|
+
readonly maxLength: 128;
|
|
708
|
+
readonly pattern: "^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$";
|
|
709
|
+
};
|
|
710
|
+
readonly VettingDocumentation: {
|
|
711
|
+
readonly title: "VettingDocumentation";
|
|
712
|
+
readonly type: "string";
|
|
713
|
+
readonly minLength: 1;
|
|
714
|
+
readonly maxLength: 64;
|
|
715
|
+
readonly pattern: "^[a-z][a-zA-Z0-9]*$";
|
|
716
|
+
readonly description: "A class of documentation, named in lowerCamelCase. Open rather than enumerated, because what documentation a vetter accepts is each vetter's own choice. Well-known values: `passport`, `nationalId`, `driverLicence`, and `none` — the vetter will attest without a document, which is the `priorAcquaintance` case. Only the class ever travels — never a document number, an image, an issuing authority or an expiry date. `none` states a policy (what a vetter accepts); a record of what was relied on expresses 'no document' as an empty list instead.";
|
|
717
|
+
};
|
|
718
|
+
readonly VettingMethod: {
|
|
719
|
+
readonly title: "VettingMethod";
|
|
720
|
+
readonly type: "string";
|
|
721
|
+
readonly enum: readonly ["inPerson", "video", "priorAcquaintance"];
|
|
722
|
+
readonly description: "How the vetter established that the person they checked is the person controlling the applicant's DID. `inPerson` — both people were physically together. `video` — a live, two-way video call. `priorAcquaintance` — the vetter has known or worked with this person over a period, and attests from that knowledge rather than from a document. A method is a description of what happened, not an assurance level: which methods count, and how many of each, is community policy.";
|
|
723
|
+
};
|
|
724
|
+
};
|
|
725
|
+
};
|
|
726
|
+
/** As {@link PAYLOAD_SCHEMA}, for the success-response variant. */
|
|
727
|
+
export declare const RESPONSE_PAYLOAD_SCHEMA: {
|
|
728
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
729
|
+
readonly $ref: "#/$defs/Response";
|
|
730
|
+
readonly $defs: {
|
|
731
|
+
readonly Duration: {
|
|
732
|
+
readonly title: "Duration";
|
|
733
|
+
readonly type: "string";
|
|
734
|
+
readonly maxLength: 32;
|
|
735
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
736
|
+
readonly description: "An ISO 8601 duration in weeks, days, hours, minutes and seconds only (e.g. `P120D`, `P2W`, `P1DT12H`, `PT15M`). Years and months are refused: their length depends on the calendar, and an age limit that means different things on different days is not a limit.";
|
|
737
|
+
};
|
|
738
|
+
readonly Criterion: {
|
|
739
|
+
readonly title: "Criterion";
|
|
740
|
+
readonly type: "object";
|
|
741
|
+
readonly additionalProperties: false;
|
|
742
|
+
readonly required: readonly ["id", "admission", "requirementsDigest"];
|
|
743
|
+
readonly properties: {
|
|
744
|
+
readonly id: {
|
|
745
|
+
readonly type: "string";
|
|
746
|
+
readonly minLength: 1;
|
|
747
|
+
readonly maxLength: 128;
|
|
748
|
+
};
|
|
749
|
+
readonly description: {
|
|
750
|
+
readonly type: "string";
|
|
751
|
+
readonly maxLength: 1024;
|
|
752
|
+
readonly description: "Plain-language summary of the criterion, authored by the community and shown to prospective applicants. Informative: where it and `vetting` disagree, `vetting` governs.";
|
|
753
|
+
};
|
|
754
|
+
readonly admission: {
|
|
755
|
+
readonly type: "string";
|
|
756
|
+
readonly enum: readonly ["automatic", "review"];
|
|
757
|
+
readonly description: "How the community decides a submission that meets this criterion. `automatic`: it admits the applicant without a person deciding. `review`: it refers the submission to an administrator, who decides.";
|
|
758
|
+
};
|
|
759
|
+
readonly presentationDefinition: {
|
|
760
|
+
readonly type: "object";
|
|
761
|
+
readonly description: "The credentials an applicant must present for this criterion (opaque here). Absent: the criterion requires no credential.";
|
|
762
|
+
};
|
|
763
|
+
readonly credentialIssuers: {
|
|
764
|
+
readonly type: "string";
|
|
765
|
+
readonly enum: readonly ["any", "community", "recognised"];
|
|
766
|
+
readonly description: "Whose credentials meet `presentationDefinition`: `community` (this community's own), `recognised` (this community's, or a community it recognises), or `any` (any issuer whose credential verifies). Present exactly when `presentationDefinition` is.";
|
|
767
|
+
};
|
|
768
|
+
readonly invitationRequired: {
|
|
769
|
+
readonly type: "boolean";
|
|
770
|
+
readonly description: "True: the criterion is met only by a submission carrying a valid, unconsumed invitation this community issued to the applicant.";
|
|
771
|
+
};
|
|
772
|
+
readonly vetting: {
|
|
773
|
+
readonly $ref: "#/$defs/VettingRequirements";
|
|
774
|
+
};
|
|
775
|
+
readonly requirementsDigest: {
|
|
776
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
777
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this criterion object with the `requirementsDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Names one version of the criterion: an applicant records it when starting an application and echoes it to vetters and at submission.";
|
|
778
|
+
};
|
|
779
|
+
};
|
|
780
|
+
readonly dependentRequired: {
|
|
781
|
+
readonly presentationDefinition: readonly ["credentialIssuers"];
|
|
782
|
+
readonly credentialIssuers: readonly ["presentationDefinition"];
|
|
783
|
+
};
|
|
784
|
+
};
|
|
785
|
+
readonly VettingRequirements: {
|
|
786
|
+
readonly title: "VettingRequirements";
|
|
787
|
+
readonly type: "object";
|
|
788
|
+
readonly additionalProperties: true;
|
|
789
|
+
readonly required: readonly ["version", "statementType", "minStatements", "acceptedMethods", "eligibleVetters"];
|
|
790
|
+
readonly description: "What identity-vetting evidence a criterion needs, beyond what a presentation-definition can express: distinct eligible vetters, per-method floors, independence caps. Every number is the community's own policy. This schema supplies no defaults — an absent optional member means the community imposes no constraint of that kind, never that some protocol value applies. Deliberately open: a consumer MUST ignore members it does not recognise, so a community publishing a newer shape does not make an older client unable to read the rest. Durations: `maxStatementAge` — a statement older than this at decision time does not count (absent: no limit beyond the statement's own validity); `decisionSla` — how long after submission the community undertakes to decide, including on a referred application; `requirementsGrace` — how long an application started under an earlier `requirementsDigest` is still evaluated under that version.";
|
|
791
|
+
readonly properties: {
|
|
792
|
+
readonly version: {
|
|
793
|
+
readonly type: "string";
|
|
794
|
+
readonly pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$";
|
|
795
|
+
readonly description: "Version of this requirements object's shape. `0.1` for the members defined here.";
|
|
796
|
+
};
|
|
797
|
+
readonly statementType: {
|
|
798
|
+
readonly type: "string";
|
|
799
|
+
readonly format: "uri";
|
|
800
|
+
readonly minLength: 1;
|
|
801
|
+
readonly maxLength: 512;
|
|
802
|
+
readonly description: "The predicate IRI a counted vetting statement carries in `credentialSubject.predicate` — `https://registry.trustoverip.org/dtg/vsc/vetted/1`, the DTG VSC registry's identity-vetting predicate, or a predicate in a namespace the community controls — registered as one the community accepts via vtc/endorsement-types/register. A statement under any other predicate does not count.";
|
|
803
|
+
};
|
|
804
|
+
readonly minStatements: {
|
|
805
|
+
readonly type: "integer";
|
|
806
|
+
readonly minimum: 1;
|
|
807
|
+
readonly description: "How many counted statements are needed, counting each vetter once however many DIDs they hold.";
|
|
808
|
+
};
|
|
809
|
+
readonly minByMethod: {
|
|
810
|
+
readonly type: "object";
|
|
811
|
+
readonly propertyNames: {
|
|
812
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
813
|
+
};
|
|
814
|
+
readonly additionalProperties: {
|
|
815
|
+
readonly type: "integer";
|
|
816
|
+
readonly minimum: 0;
|
|
817
|
+
};
|
|
818
|
+
readonly description: "Per-method floors within `minStatements` — e.g. `{ \"inPerson\": 1 }`. Every method named MUST also be in `acceptedMethods`. Absent: no method floor.";
|
|
819
|
+
};
|
|
820
|
+
readonly acceptedMethods: {
|
|
821
|
+
readonly type: "array";
|
|
822
|
+
readonly minItems: 1;
|
|
823
|
+
readonly uniqueItems: true;
|
|
824
|
+
readonly items: {
|
|
825
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
826
|
+
};
|
|
827
|
+
readonly description: "Methods whose statements count at all.";
|
|
828
|
+
};
|
|
829
|
+
readonly acceptedDocumentClasses: {
|
|
830
|
+
readonly type: "array";
|
|
831
|
+
readonly minItems: 1;
|
|
832
|
+
readonly uniqueItems: true;
|
|
833
|
+
readonly items: {
|
|
834
|
+
readonly $ref: "#/$defs/VettingDocumentation";
|
|
835
|
+
};
|
|
836
|
+
readonly description: "Documentation a statement must have relied on in order to count. Absent — the expected case — means each vetter decides what documentation they accept, including none for prior acquaintance, and the community counts what they attest.";
|
|
837
|
+
};
|
|
838
|
+
readonly requiredClaims: {
|
|
839
|
+
readonly type: "array";
|
|
840
|
+
readonly uniqueItems: true;
|
|
841
|
+
readonly items: {
|
|
842
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
843
|
+
};
|
|
844
|
+
readonly description: "Claim types the applicant's Vetting Card must carry, which the identity commitment is computed over, and which a counted statement must list as verified. Absent: none.";
|
|
845
|
+
};
|
|
846
|
+
readonly optionalClaims: {
|
|
847
|
+
readonly type: "array";
|
|
848
|
+
readonly uniqueItems: true;
|
|
849
|
+
readonly items: {
|
|
850
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
851
|
+
};
|
|
852
|
+
readonly description: "Claim types an applicant MAY add to the card and a vetter MAY verify. They never affect whether a statement counts.";
|
|
853
|
+
};
|
|
854
|
+
readonly maxStatementAge: {
|
|
855
|
+
readonly $ref: "#/$defs/Duration";
|
|
856
|
+
};
|
|
857
|
+
readonly eligibleVetters: {
|
|
858
|
+
readonly type: "object";
|
|
859
|
+
readonly additionalProperties: false;
|
|
860
|
+
readonly required: readonly ["role"];
|
|
861
|
+
readonly properties: {
|
|
862
|
+
readonly role: {
|
|
863
|
+
readonly type: "string";
|
|
864
|
+
readonly minLength: 1;
|
|
865
|
+
readonly maxLength: 128;
|
|
866
|
+
readonly pattern: "^[a-zA-Z][a-zA-Z0-9_-]*$";
|
|
867
|
+
readonly description: "The role a statement's issuer must hold, matched as the action `role:<role>` in a Verifiable Authority Credential (`AuthorityCredential`) the community issued to that issuer, whose `authority.scope` is the community's DID (see `vtc/vetting/vetters/grant/0.1`). A statement counts only if its issuer holds such a credential.";
|
|
868
|
+
};
|
|
869
|
+
};
|
|
870
|
+
readonly description: "How a vetter's eligibility is established.";
|
|
871
|
+
};
|
|
872
|
+
readonly independence: {
|
|
873
|
+
readonly type: "object";
|
|
874
|
+
readonly additionalProperties: false;
|
|
875
|
+
readonly properties: {
|
|
876
|
+
readonly maxByDeclaredRelationship: {
|
|
877
|
+
readonly type: "object";
|
|
878
|
+
readonly propertyNames: {
|
|
879
|
+
readonly $ref: "#/$defs/VettingRelationship";
|
|
880
|
+
};
|
|
881
|
+
readonly additionalProperties: {
|
|
882
|
+
readonly type: "integer";
|
|
883
|
+
readonly minimum: 0;
|
|
884
|
+
};
|
|
885
|
+
readonly description: "The most counted statements that may come from vetters declaring each relationship — e.g. `{ \"family\": 0 }`.";
|
|
886
|
+
};
|
|
887
|
+
readonly requireConsistentIdentityCommitment: {
|
|
888
|
+
readonly type: "boolean";
|
|
889
|
+
readonly description: "When true, every counted statement must carry the same identity commitment — all vetters verified the same claimed identity. Absent: false.";
|
|
890
|
+
};
|
|
891
|
+
};
|
|
892
|
+
readonly description: "Caps on how much evidence may come from people close to the applicant. Absent: no caps.";
|
|
893
|
+
};
|
|
894
|
+
readonly invitation: {
|
|
895
|
+
readonly type: "string";
|
|
896
|
+
readonly enum: readonly ["required", "optional", "none"];
|
|
897
|
+
readonly description: "Whether an invitation credential must accompany the statements at submission (`required`), may (`optional`), or plays no part (`none`). Absent: the presentation-definition alone governs.";
|
|
898
|
+
};
|
|
899
|
+
readonly decisionSla: {
|
|
900
|
+
readonly $ref: "#/$defs/Duration";
|
|
901
|
+
};
|
|
902
|
+
readonly requirementsGrace: {
|
|
903
|
+
readonly $ref: "#/$defs/Duration";
|
|
904
|
+
};
|
|
905
|
+
readonly governanceFrameworkUrl: {
|
|
906
|
+
readonly type: "string";
|
|
907
|
+
readonly format: "uri";
|
|
908
|
+
readonly pattern: "^https://";
|
|
909
|
+
readonly maxLength: 2048;
|
|
910
|
+
readonly description: "Where the community's vetting governance — including the attestation text vetters sign — is published.";
|
|
911
|
+
};
|
|
912
|
+
readonly ext: {
|
|
913
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1, for vetting parameters this version does not enumerate. A community publishing an admission mode the base members cannot express — the zero-knowledge parameters an applicant proves against, say — puts them under a namespace it controls, rather than waiting for a version that names them.\n\nThis object is already `additionalProperties: true`, so an unknown member here has always validated. That is not the same as reaching a consumer: a generated type names the members this schema declares and drops the rest, so an undeclared member is parsed and discarded, and it is discarded again on the re-serialization `requirementsDigest` is computed over. `ext` is a declared member, so it survives both.";
|
|
914
|
+
readonly $ref: "#/$defs/Ext";
|
|
915
|
+
};
|
|
916
|
+
readonly extCritical: {
|
|
917
|
+
readonly description: "Namespaces of `ext` an applicant MUST understand or refuse, per SPEC.md §4.5.1.\n\nA community marks a namespace here when applying under this criterion without understanding it would mean something other than what the community requires — an applicant that ignored a hidden-vetting namespace, for instance, would submit named statements to a criterion whose whole point was that it does not receive them. An applicant that does not recognize a marked namespace stops rather than downgrading silently.\n\nAbsent, which is the common case, every namespace under `ext` is advisory and ignorable.";
|
|
918
|
+
readonly $ref: "#/$defs/ExtCritical";
|
|
919
|
+
};
|
|
920
|
+
};
|
|
921
|
+
};
|
|
922
|
+
readonly CommunityBranding: {
|
|
923
|
+
readonly title: "CommunityBranding";
|
|
924
|
+
readonly type: "object";
|
|
925
|
+
readonly additionalProperties: false;
|
|
926
|
+
readonly description: "OPTIONAL. How the community asks to be shown to a prospective applicant: a name, an accent colour and a logo. Presentation only, self-asserted and unverified — `communityDid` identifies the community, never `branding`. Not part of any criterion, so not covered by a `requirementsDigest`. Every member is optional.";
|
|
927
|
+
readonly properties: {
|
|
928
|
+
readonly displayName: {
|
|
929
|
+
readonly type: "string";
|
|
930
|
+
readonly minLength: 1;
|
|
931
|
+
readonly maxLength: 128;
|
|
932
|
+
readonly description: "The community's name as it asks to be shown.";
|
|
933
|
+
};
|
|
934
|
+
readonly accentColor: {
|
|
935
|
+
readonly type: "string";
|
|
936
|
+
readonly pattern: "^#[0-9a-fA-F]{6}$";
|
|
937
|
+
readonly description: "An sRGB colour as `#rrggbb`, compared case-insensitively. A community SHOULD write it in lower case.";
|
|
938
|
+
};
|
|
939
|
+
readonly logoUrl: {
|
|
940
|
+
readonly type: "string";
|
|
941
|
+
readonly format: "uri";
|
|
942
|
+
readonly pattern: "^https://";
|
|
943
|
+
readonly maxLength: 2048;
|
|
944
|
+
readonly description: "An https URL of the community's logo. Fetched by the client, so an untrusted image from wherever it points.";
|
|
945
|
+
};
|
|
946
|
+
readonly ext: {
|
|
947
|
+
readonly $ref: "#/$defs/Ext";
|
|
948
|
+
};
|
|
949
|
+
};
|
|
950
|
+
};
|
|
951
|
+
readonly Response: {
|
|
952
|
+
readonly $anchor: "response";
|
|
953
|
+
readonly title: "VTC Join-Requests Manifest — response payload";
|
|
954
|
+
readonly type: "object";
|
|
955
|
+
readonly additionalProperties: false;
|
|
956
|
+
readonly required: readonly ["communityDid", "criteria"];
|
|
957
|
+
readonly properties: {
|
|
958
|
+
readonly communityDid: {
|
|
959
|
+
readonly type: "string";
|
|
960
|
+
readonly pattern: "^did:";
|
|
961
|
+
};
|
|
962
|
+
readonly criteria: {
|
|
963
|
+
readonly type: "array";
|
|
964
|
+
readonly items: {
|
|
965
|
+
readonly $ref: "#/$defs/Criterion";
|
|
966
|
+
};
|
|
967
|
+
};
|
|
968
|
+
readonly requestedAttributes: {
|
|
969
|
+
readonly type: "array";
|
|
970
|
+
readonly maxItems: 32;
|
|
971
|
+
readonly description: "What the community asks an applicant to tell it about themselves, as claim types — never values. Answered in persona terms: the applicant's agent discloses those attributes from the face the applicant chooses, and they arrive on vtc/join-requests/submit as `attributes`. SELF-ASSERTED: a community MUST NOT describe an answer as verified, and MUST NOT make a decision that assumes it is. Outside every criterion, so no `requirementsDigest` covers it. Absent when the community asks nothing.";
|
|
972
|
+
readonly items: {
|
|
973
|
+
readonly type: "object";
|
|
974
|
+
readonly additionalProperties: false;
|
|
975
|
+
readonly required: readonly ["type"];
|
|
976
|
+
readonly properties: {
|
|
977
|
+
readonly type: {
|
|
978
|
+
readonly type: "string";
|
|
979
|
+
readonly minLength: 1;
|
|
980
|
+
readonly maxLength: 128;
|
|
981
|
+
readonly pattern: "^(x:)?[a-z][A-Za-z0-9]*(\\.[a-z][A-Za-z0-9]*)*$";
|
|
982
|
+
readonly description: "A claim-type token from the persona claim-type registry (persona/_shared/0.1/CLAIM-TYPES.md) — `name.display`, `address.country` — or an `x:` extension token.";
|
|
983
|
+
};
|
|
984
|
+
readonly required: {
|
|
985
|
+
readonly type: "boolean";
|
|
986
|
+
readonly default: true;
|
|
987
|
+
readonly description: "False for an attribute the applicant may decline. A submission missing a required one is refused with vtc/join-requests/submit:attributesMissing.";
|
|
988
|
+
};
|
|
989
|
+
readonly purpose: {
|
|
990
|
+
readonly type: "string";
|
|
991
|
+
readonly maxLength: 256;
|
|
992
|
+
readonly description: "Why the community asks, in words shown to the applicant before they disclose.";
|
|
993
|
+
};
|
|
994
|
+
};
|
|
995
|
+
};
|
|
996
|
+
};
|
|
997
|
+
readonly branding: {
|
|
998
|
+
readonly $ref: "#/$defs/CommunityBranding";
|
|
999
|
+
};
|
|
1000
|
+
readonly directoryDisclosure: {
|
|
1001
|
+
readonly $ref: "#/$defs/DirectoryDisclosure";
|
|
1002
|
+
readonly description: "Present exactly where the community offers a member directory: the statement, generated from its configuration, of what the directory would disclose about a member and to whom — the same statement vtc/directory/disclosure returns. Outside every criterion, so no `requirementsDigest` covers it; it names itself with its own `statementDigest`.";
|
|
1003
|
+
};
|
|
1004
|
+
readonly ext: {
|
|
1005
|
+
readonly $ref: "#/$defs/Ext";
|
|
1006
|
+
};
|
|
1007
|
+
};
|
|
1008
|
+
};
|
|
1009
|
+
readonly Ext: {
|
|
1010
|
+
readonly title: "Ext";
|
|
1011
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
1012
|
+
readonly type: "object";
|
|
1013
|
+
readonly minProperties: 1;
|
|
1014
|
+
readonly additionalProperties: true;
|
|
1015
|
+
readonly propertyNames: {
|
|
1016
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
1017
|
+
};
|
|
1018
|
+
};
|
|
1019
|
+
readonly DirectoryDisclosure: {
|
|
1020
|
+
readonly title: "DirectoryDisclosure";
|
|
1021
|
+
readonly description: "The statement itself. Every member is generated from the community's configuration when the statement is read. `statementDigest` names this exact statement, so an applicant can record which one it was shown.";
|
|
1022
|
+
readonly type: "object";
|
|
1023
|
+
readonly additionalProperties: false;
|
|
1024
|
+
readonly required: readonly ["fields", "newCard", "membershipIdentifiers", "adminNotes", "externalCards", "statementDigest"];
|
|
1025
|
+
readonly properties: {
|
|
1026
|
+
readonly fields: {
|
|
1027
|
+
readonly type: "array";
|
|
1028
|
+
readonly maxItems: 128;
|
|
1029
|
+
readonly items: {
|
|
1030
|
+
readonly $ref: "#/$defs/DisclosedField";
|
|
1031
|
+
};
|
|
1032
|
+
readonly description: "Every active field, base and community-defined, in display order. A base field the community has disabled is absent, which is how a reader learns it is not collected.";
|
|
1033
|
+
};
|
|
1034
|
+
readonly newCard: {
|
|
1035
|
+
readonly $ref: "#/$defs/NewCardDefaults";
|
|
1036
|
+
};
|
|
1037
|
+
readonly membershipIdentifiers: {
|
|
1038
|
+
readonly $ref: "#/$defs/Audience";
|
|
1039
|
+
readonly description: "The widest audience a member's membership identifier — the DID they joined with — can reach through the directory: the ceiling of the base field `did`, or `admins` where that field is disabled. `members` or `public` means a member may choose to show it that widely; a new card never shows it beyond `admins` (VTI-DIR-042). Administrators always see it.";
|
|
1040
|
+
};
|
|
1041
|
+
readonly adminNotes: {
|
|
1042
|
+
readonly type: "boolean";
|
|
1043
|
+
readonly description: "Whether administrators keep notes about members. Notes are never on a card and never reach another member; a member may ask for the notes about them.";
|
|
1044
|
+
};
|
|
1045
|
+
readonly groups: {
|
|
1046
|
+
readonly $ref: "#/$defs/GroupDisclosure";
|
|
1047
|
+
};
|
|
1048
|
+
readonly externalCards: {
|
|
1049
|
+
readonly type: "boolean";
|
|
1050
|
+
readonly description: "Whether a member may publish a card beyond the community: their `public` values, signed by them, offered through the community's trust registry. Always the member's own choice, and off on a new card. False where the community cannot publish external cards.";
|
|
1051
|
+
};
|
|
1052
|
+
readonly statementDigest: {
|
|
1053
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
1054
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this statement with the `statementDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Changes exactly when what the statement says changes.";
|
|
1055
|
+
};
|
|
1056
|
+
readonly ext: {
|
|
1057
|
+
readonly $ref: "#/$defs/Ext";
|
|
1058
|
+
};
|
|
1059
|
+
};
|
|
1060
|
+
};
|
|
1061
|
+
readonly GroupDisclosure: {
|
|
1062
|
+
readonly title: "GroupDisclosure";
|
|
1063
|
+
readonly description: "Present when the community has groups. A member of a group holds a credential, issued by the group's own identifier, that evidences their membership, and can present it outside the community — which is why an applicant is told.";
|
|
1064
|
+
readonly type: "object";
|
|
1065
|
+
readonly additionalProperties: false;
|
|
1066
|
+
readonly required: readonly ["credentialValidity"];
|
|
1067
|
+
readonly properties: {
|
|
1068
|
+
readonly credentialValidity: {
|
|
1069
|
+
readonly type: "string";
|
|
1070
|
+
readonly maxLength: 32;
|
|
1071
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
1072
|
+
readonly description: "How long each group membership credential is valid for, as an ISO 8601 duration in weeks, days, hours, minutes and seconds (`P30D`). It is renewed while the member stays in the group, and a credential already issued stays valid until it expires even after its holder leaves.";
|
|
1073
|
+
};
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
1076
|
+
readonly NewCardDefaults: {
|
|
1077
|
+
readonly title: "NewCardDefaults";
|
|
1078
|
+
readonly description: "The discoverability a card has when the community creates it, before its member chooses. A new card is never published beyond the community (VTI-DIR-042), so there is no member for that here: `externalCards` says whether the member may turn it on.";
|
|
1079
|
+
readonly type: "object";
|
|
1080
|
+
readonly additionalProperties: false;
|
|
1081
|
+
readonly required: readonly ["listing", "search"];
|
|
1082
|
+
readonly properties: {
|
|
1083
|
+
readonly listing: {
|
|
1084
|
+
readonly $ref: "#/$defs/Listing";
|
|
1085
|
+
readonly description: "The listing a new card starts with: the community's `defaultListing` (vtc/directory/fields/list). Every member may always choose `hidden`.";
|
|
1086
|
+
};
|
|
1087
|
+
readonly search: {
|
|
1088
|
+
readonly type: "string";
|
|
1089
|
+
readonly enum: readonly ["byName", "exactNickname", "off"];
|
|
1090
|
+
readonly description: "What a member's search may match, as the card's `discoverability.search`.";
|
|
1091
|
+
};
|
|
1092
|
+
readonly introductions: {
|
|
1093
|
+
readonly $ref: "#/$defs/Introductions";
|
|
1094
|
+
readonly description: "From whom a new card accepts introductions. Absent where the community does not deliver introductions.";
|
|
1095
|
+
};
|
|
1096
|
+
};
|
|
1097
|
+
};
|
|
1098
|
+
readonly Introductions: {
|
|
1099
|
+
readonly title: "Introductions";
|
|
1100
|
+
readonly description: "Who may ask the community to introduce them to this member. `anyone`: any active member who can find the entry. `groups`: only members who share a community group with them. `connections`: only members holding an attributed, in-force verified relationship with them. `off`: nobody. A refused introduction is never reported to its sender.";
|
|
1101
|
+
readonly type: "string";
|
|
1102
|
+
readonly enum: readonly ["anyone", "groups", "connections", "off"];
|
|
1103
|
+
};
|
|
1104
|
+
readonly Listing: {
|
|
1105
|
+
readonly title: "Listing";
|
|
1106
|
+
readonly description: "Whether members can find the entry. `listed`: it appears when members browse. `findable`: it does not appear when browsing, but a search that matches it under `search` returns it. `hidden`: no member finds it by browsing or searching; administrators still see it, and members who share a group that shows its members see it in that group's member list.";
|
|
1107
|
+
readonly type: "string";
|
|
1108
|
+
readonly enum: readonly ["listed", "findable", "hidden"];
|
|
1109
|
+
};
|
|
1110
|
+
readonly DisclosedField: {
|
|
1111
|
+
readonly title: "DisclosedField";
|
|
1112
|
+
readonly description: "One active field of the community's directory, as an applicant needs to see it: what it is, who writes its value, the widest audience it may ever reach and the audience a new card gives it. Disabled and retired fields are not listed: no projection shows them.";
|
|
1113
|
+
readonly type: "object";
|
|
1114
|
+
readonly additionalProperties: false;
|
|
1115
|
+
readonly required: readonly ["key", "label", "type", "source", "ceiling", "defaultVisibility", "searchable"];
|
|
1116
|
+
readonly properties: {
|
|
1117
|
+
readonly key: {
|
|
1118
|
+
readonly $ref: "#/$defs/FieldKey";
|
|
1119
|
+
};
|
|
1120
|
+
readonly label: {
|
|
1121
|
+
readonly $ref: "#/$defs/FieldLabel";
|
|
1122
|
+
};
|
|
1123
|
+
readonly description: {
|
|
1124
|
+
readonly $ref: "#/$defs/FieldDescription";
|
|
1125
|
+
};
|
|
1126
|
+
readonly type: {
|
|
1127
|
+
readonly $ref: "#/$defs/FieldType";
|
|
1128
|
+
};
|
|
1129
|
+
readonly source: {
|
|
1130
|
+
readonly $ref: "#/$defs/FieldSource";
|
|
1131
|
+
readonly description: "Who writes the value. `admin` and `credential` matter most to an applicant: an `admin` field holds what the community asserts about the member, which the member reads and cannot change.";
|
|
1132
|
+
};
|
|
1133
|
+
readonly ceiling: {
|
|
1134
|
+
readonly $ref: "#/$defs/Audience";
|
|
1135
|
+
readonly description: "The widest audience the field may ever reach, whatever the member chooses.";
|
|
1136
|
+
};
|
|
1137
|
+
readonly defaultVisibility: {
|
|
1138
|
+
readonly $ref: "#/$defs/Audience";
|
|
1139
|
+
readonly description: "The audience a new card gives the field until its member chooses. Never wider than `ceiling`.";
|
|
1140
|
+
};
|
|
1141
|
+
readonly searchable: {
|
|
1142
|
+
readonly type: "boolean";
|
|
1143
|
+
readonly description: "Whether a member's search may match the field, within what the searcher may see.";
|
|
1144
|
+
};
|
|
1145
|
+
readonly facet: {
|
|
1146
|
+
readonly type: "boolean";
|
|
1147
|
+
readonly description: "Whether members may filter on the field and see counts by its values. Absent: false.";
|
|
1148
|
+
};
|
|
1149
|
+
};
|
|
1150
|
+
};
|
|
1151
|
+
readonly Audience: {
|
|
1152
|
+
readonly title: "Audience";
|
|
1153
|
+
readonly description: "Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\n\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.";
|
|
1154
|
+
readonly type: "string";
|
|
1155
|
+
readonly enum: readonly ["admins", "groups", "connections", "members", "public"];
|
|
1156
|
+
};
|
|
1157
|
+
readonly FieldSource: {
|
|
1158
|
+
readonly title: "FieldSource";
|
|
1159
|
+
readonly description: "Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.";
|
|
1160
|
+
readonly type: "string";
|
|
1161
|
+
readonly enum: readonly ["member", "admin", "credential", "derived"];
|
|
1162
|
+
};
|
|
1163
|
+
readonly FieldType: {
|
|
1164
|
+
readonly title: "FieldType";
|
|
1165
|
+
readonly description: "The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.";
|
|
1166
|
+
readonly type: "string";
|
|
1167
|
+
readonly enum: readonly ["text", "longText", "url", "email", "phone", "enum", "multiEnum", "date", "country", "image", "did", "claim"];
|
|
1168
|
+
};
|
|
1169
|
+
readonly FieldDescription: {
|
|
1170
|
+
readonly title: "FieldDescription";
|
|
1171
|
+
readonly type: "string";
|
|
1172
|
+
readonly minLength: 1;
|
|
1173
|
+
readonly maxLength: 280;
|
|
1174
|
+
readonly description: "Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.";
|
|
1175
|
+
};
|
|
1176
|
+
readonly FieldLabel: {
|
|
1177
|
+
readonly title: "FieldLabel";
|
|
1178
|
+
readonly type: "string";
|
|
1179
|
+
readonly minLength: 1;
|
|
1180
|
+
readonly maxLength: 64;
|
|
1181
|
+
readonly description: "What readers see as the field's name. Plain text.";
|
|
1182
|
+
};
|
|
1183
|
+
readonly FieldKey: {
|
|
1184
|
+
readonly title: "FieldKey";
|
|
1185
|
+
readonly description: "Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.";
|
|
1186
|
+
readonly type: "string";
|
|
1187
|
+
readonly minLength: 1;
|
|
1188
|
+
readonly maxLength: 128;
|
|
1189
|
+
readonly pattern: "^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$";
|
|
1190
|
+
};
|
|
1191
|
+
readonly DigestMultibase: {
|
|
1192
|
+
readonly title: "DigestMultibase";
|
|
1193
|
+
readonly description: "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.";
|
|
1194
|
+
readonly type: "string";
|
|
1195
|
+
readonly minLength: 16;
|
|
1196
|
+
readonly pattern: "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$";
|
|
1197
|
+
readonly examples: readonly ["zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"];
|
|
1198
|
+
};
|
|
1199
|
+
readonly ExtCritical: {
|
|
1200
|
+
readonly title: "ExtCritical";
|
|
1201
|
+
readonly description: "Names the `ext` namespaces a consumer MUST understand or refuse, per SPEC.md §4.5.1.\n\nEvery entry MUST be an immediate key of the sibling `ext` object at the same level; an entry naming an absent namespace is non-conforming and the consumer rejects the document with `malformedRequest`. A consumer that does not recognize a namespace named here MUST NOT process the document as though the namespace were absent, and rejects it with `unsupportedExtension` — the exception to the rule that unrecognized namespaces are ignored.\n\nA producer marks a namespace only where the document's meaning depends on it. Marking one that merely carries a hint or an annotation turns every consumer that has not implemented it into a failure where it would otherwise have interoperated. JSON Schema cannot check either of those rules: that an entry names a present namespace is checkable only against the sibling `ext`, and whether a namespace is load-bearing is not a schema question at all. Both are consumer-side checks.";
|
|
1202
|
+
readonly type: "array";
|
|
1203
|
+
readonly minItems: 1;
|
|
1204
|
+
readonly uniqueItems: true;
|
|
1205
|
+
readonly items: {
|
|
1206
|
+
readonly type: "string";
|
|
1207
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
1208
|
+
};
|
|
1209
|
+
readonly examples: readonly [readonly ["org.openvtc.hidden-vetting"]];
|
|
1210
|
+
};
|
|
1211
|
+
readonly VettingRelationship: {
|
|
1212
|
+
readonly title: "VettingRelationship";
|
|
1213
|
+
readonly type: "string";
|
|
1214
|
+
readonly enum: readonly ["none", "communityColleague", "sameEmployer", "family", "otherPersonal"];
|
|
1215
|
+
readonly description: "The vetter's own declaration of how they relate to the applicant. Declared, not verified: it exists so community policy can cap how much evidence comes from people close to the applicant, and a false declaration is the vetter's attributable act.";
|
|
1216
|
+
};
|
|
1217
|
+
readonly ClaimType: {
|
|
1218
|
+
readonly title: "ClaimType";
|
|
1219
|
+
readonly description: "The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\n\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\n\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.";
|
|
1220
|
+
readonly type: "string";
|
|
1221
|
+
readonly minLength: 1;
|
|
1222
|
+
readonly maxLength: 128;
|
|
1223
|
+
readonly pattern: "^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$";
|
|
1224
|
+
};
|
|
1225
|
+
readonly VettingDocumentation: {
|
|
1226
|
+
readonly title: "VettingDocumentation";
|
|
1227
|
+
readonly type: "string";
|
|
1228
|
+
readonly minLength: 1;
|
|
1229
|
+
readonly maxLength: 64;
|
|
1230
|
+
readonly pattern: "^[a-z][a-zA-Z0-9]*$";
|
|
1231
|
+
readonly description: "A class of documentation, named in lowerCamelCase. Open rather than enumerated, because what documentation a vetter accepts is each vetter's own choice. Well-known values: `passport`, `nationalId`, `driverLicence`, and `none` — the vetter will attest without a document, which is the `priorAcquaintance` case. Only the class ever travels — never a document number, an image, an issuing authority or an expiry date. `none` states a policy (what a vetter accepts); a record of what was relied on expresses 'no document' as an empty list instead.";
|
|
1232
|
+
};
|
|
1233
|
+
readonly VettingMethod: {
|
|
1234
|
+
readonly title: "VettingMethod";
|
|
1235
|
+
readonly type: "string";
|
|
1236
|
+
readonly enum: readonly ["inPerson", "video", "priorAcquaintance"];
|
|
1237
|
+
readonly description: "How the vetter established that the person they checked is the person controlling the applicant's DID. `inPerson` — both people were physically together. `video` — a live, two-way video call. `priorAcquaintance` — the vetter has known or worked with this person over a period, and attests from that knowledge rather than from a document. A method is a description of what happened, not an assurance level: which methods count, and how many of each, is community policy.";
|
|
1238
|
+
};
|
|
1239
|
+
};
|
|
1240
|
+
};
|
|
1241
|
+
/**
|
|
1242
|
+
* SPEC.md §7.2 policy for the request variant, from this specification's
|
|
1243
|
+
* front matter. Pass to `consumeInbound` — items 5b, 7 and 8 are
|
|
1244
|
+
* per-specification and cannot be derived from the document alone, and
|
|
1245
|
+
* item 2 needs the schema this carries.
|
|
1246
|
+
*/
|
|
1247
|
+
export declare const SPEC: {
|
|
1248
|
+
readonly typeUri: "https://trusttasks.org/spec/vtc/join-requests/manifest/0.4";
|
|
1249
|
+
readonly isBearer: false;
|
|
1250
|
+
readonly isProofRequired: false;
|
|
1251
|
+
readonly isRecipientRequired: true;
|
|
1252
|
+
readonly isIssuedAtRequired: false;
|
|
1253
|
+
readonly payloadSchema: {
|
|
1254
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
1255
|
+
readonly $id: "https://trusttasks.org/spec/vtc/join-requests/manifest/0.4";
|
|
1256
|
+
readonly title: "VTC Join-Requests Manifest — payload";
|
|
1257
|
+
readonly description: "Discover a community's join criteria before applying. The request carries nothing. Version 0.2 adds, per criterion, an optional `vetting` requirements object — how many identity-vetting statements a community needs, by which methods, from whom — and a `requirementsDigest` that names the exact version of the criterion an applicant started under. The response may also carry `branding`, how the community asks to be shown. Version 0.4 adds `directoryDisclosure`: where the community has a member directory, the statement of what it would disclose about a member and to whom, so an applicant reads it before applying.";
|
|
1258
|
+
readonly type: "object";
|
|
1259
|
+
readonly additionalProperties: false;
|
|
1260
|
+
readonly properties: {
|
|
1261
|
+
readonly ext: {
|
|
1262
|
+
readonly $ref: "#/$defs/Ext";
|
|
1263
|
+
};
|
|
1264
|
+
};
|
|
1265
|
+
readonly $defs: {
|
|
1266
|
+
readonly Duration: {
|
|
1267
|
+
readonly title: "Duration";
|
|
1268
|
+
readonly type: "string";
|
|
1269
|
+
readonly maxLength: 32;
|
|
1270
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
1271
|
+
readonly description: "An ISO 8601 duration in weeks, days, hours, minutes and seconds only (e.g. `P120D`, `P2W`, `P1DT12H`, `PT15M`). Years and months are refused: their length depends on the calendar, and an age limit that means different things on different days is not a limit.";
|
|
1272
|
+
};
|
|
1273
|
+
readonly Criterion: {
|
|
1274
|
+
readonly title: "Criterion";
|
|
1275
|
+
readonly type: "object";
|
|
1276
|
+
readonly additionalProperties: false;
|
|
1277
|
+
readonly required: readonly ["id", "admission", "requirementsDigest"];
|
|
1278
|
+
readonly properties: {
|
|
1279
|
+
readonly id: {
|
|
1280
|
+
readonly type: "string";
|
|
1281
|
+
readonly minLength: 1;
|
|
1282
|
+
readonly maxLength: 128;
|
|
1283
|
+
};
|
|
1284
|
+
readonly description: {
|
|
1285
|
+
readonly type: "string";
|
|
1286
|
+
readonly maxLength: 1024;
|
|
1287
|
+
readonly description: "Plain-language summary of the criterion, authored by the community and shown to prospective applicants. Informative: where it and `vetting` disagree, `vetting` governs.";
|
|
1288
|
+
};
|
|
1289
|
+
readonly admission: {
|
|
1290
|
+
readonly type: "string";
|
|
1291
|
+
readonly enum: readonly ["automatic", "review"];
|
|
1292
|
+
readonly description: "How the community decides a submission that meets this criterion. `automatic`: it admits the applicant without a person deciding. `review`: it refers the submission to an administrator, who decides.";
|
|
1293
|
+
};
|
|
1294
|
+
readonly presentationDefinition: {
|
|
1295
|
+
readonly type: "object";
|
|
1296
|
+
readonly description: "The credentials an applicant must present for this criterion (opaque here). Absent: the criterion requires no credential.";
|
|
1297
|
+
};
|
|
1298
|
+
readonly credentialIssuers: {
|
|
1299
|
+
readonly type: "string";
|
|
1300
|
+
readonly enum: readonly ["any", "community", "recognised"];
|
|
1301
|
+
readonly description: "Whose credentials meet `presentationDefinition`: `community` (this community's own), `recognised` (this community's, or a community it recognises), or `any` (any issuer whose credential verifies). Present exactly when `presentationDefinition` is.";
|
|
1302
|
+
};
|
|
1303
|
+
readonly invitationRequired: {
|
|
1304
|
+
readonly type: "boolean";
|
|
1305
|
+
readonly description: "True: the criterion is met only by a submission carrying a valid, unconsumed invitation this community issued to the applicant.";
|
|
1306
|
+
};
|
|
1307
|
+
readonly vetting: {
|
|
1308
|
+
readonly $ref: "#/$defs/VettingRequirements";
|
|
1309
|
+
};
|
|
1310
|
+
readonly requirementsDigest: {
|
|
1311
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
1312
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this criterion object with the `requirementsDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Names one version of the criterion: an applicant records it when starting an application and echoes it to vetters and at submission.";
|
|
1313
|
+
};
|
|
1314
|
+
};
|
|
1315
|
+
readonly dependentRequired: {
|
|
1316
|
+
readonly presentationDefinition: readonly ["credentialIssuers"];
|
|
1317
|
+
readonly credentialIssuers: readonly ["presentationDefinition"];
|
|
1318
|
+
};
|
|
1319
|
+
};
|
|
1320
|
+
readonly VettingRequirements: {
|
|
1321
|
+
readonly title: "VettingRequirements";
|
|
1322
|
+
readonly type: "object";
|
|
1323
|
+
readonly additionalProperties: true;
|
|
1324
|
+
readonly required: readonly ["version", "statementType", "minStatements", "acceptedMethods", "eligibleVetters"];
|
|
1325
|
+
readonly description: "What identity-vetting evidence a criterion needs, beyond what a presentation-definition can express: distinct eligible vetters, per-method floors, independence caps. Every number is the community's own policy. This schema supplies no defaults — an absent optional member means the community imposes no constraint of that kind, never that some protocol value applies. Deliberately open: a consumer MUST ignore members it does not recognise, so a community publishing a newer shape does not make an older client unable to read the rest. Durations: `maxStatementAge` — a statement older than this at decision time does not count (absent: no limit beyond the statement's own validity); `decisionSla` — how long after submission the community undertakes to decide, including on a referred application; `requirementsGrace` — how long an application started under an earlier `requirementsDigest` is still evaluated under that version.";
|
|
1326
|
+
readonly properties: {
|
|
1327
|
+
readonly version: {
|
|
1328
|
+
readonly type: "string";
|
|
1329
|
+
readonly pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$";
|
|
1330
|
+
readonly description: "Version of this requirements object's shape. `0.1` for the members defined here.";
|
|
1331
|
+
};
|
|
1332
|
+
readonly statementType: {
|
|
1333
|
+
readonly type: "string";
|
|
1334
|
+
readonly format: "uri";
|
|
1335
|
+
readonly minLength: 1;
|
|
1336
|
+
readonly maxLength: 512;
|
|
1337
|
+
readonly description: "The predicate IRI a counted vetting statement carries in `credentialSubject.predicate` — `https://registry.trustoverip.org/dtg/vsc/vetted/1`, the DTG VSC registry's identity-vetting predicate, or a predicate in a namespace the community controls — registered as one the community accepts via vtc/endorsement-types/register. A statement under any other predicate does not count.";
|
|
1338
|
+
};
|
|
1339
|
+
readonly minStatements: {
|
|
1340
|
+
readonly type: "integer";
|
|
1341
|
+
readonly minimum: 1;
|
|
1342
|
+
readonly description: "How many counted statements are needed, counting each vetter once however many DIDs they hold.";
|
|
1343
|
+
};
|
|
1344
|
+
readonly minByMethod: {
|
|
1345
|
+
readonly type: "object";
|
|
1346
|
+
readonly propertyNames: {
|
|
1347
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
1348
|
+
};
|
|
1349
|
+
readonly additionalProperties: {
|
|
1350
|
+
readonly type: "integer";
|
|
1351
|
+
readonly minimum: 0;
|
|
1352
|
+
};
|
|
1353
|
+
readonly description: "Per-method floors within `minStatements` — e.g. `{ \"inPerson\": 1 }`. Every method named MUST also be in `acceptedMethods`. Absent: no method floor.";
|
|
1354
|
+
};
|
|
1355
|
+
readonly acceptedMethods: {
|
|
1356
|
+
readonly type: "array";
|
|
1357
|
+
readonly minItems: 1;
|
|
1358
|
+
readonly uniqueItems: true;
|
|
1359
|
+
readonly items: {
|
|
1360
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
1361
|
+
};
|
|
1362
|
+
readonly description: "Methods whose statements count at all.";
|
|
1363
|
+
};
|
|
1364
|
+
readonly acceptedDocumentClasses: {
|
|
1365
|
+
readonly type: "array";
|
|
1366
|
+
readonly minItems: 1;
|
|
1367
|
+
readonly uniqueItems: true;
|
|
1368
|
+
readonly items: {
|
|
1369
|
+
readonly $ref: "#/$defs/VettingDocumentation";
|
|
1370
|
+
};
|
|
1371
|
+
readonly description: "Documentation a statement must have relied on in order to count. Absent — the expected case — means each vetter decides what documentation they accept, including none for prior acquaintance, and the community counts what they attest.";
|
|
1372
|
+
};
|
|
1373
|
+
readonly requiredClaims: {
|
|
1374
|
+
readonly type: "array";
|
|
1375
|
+
readonly uniqueItems: true;
|
|
1376
|
+
readonly items: {
|
|
1377
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
1378
|
+
};
|
|
1379
|
+
readonly description: "Claim types the applicant's Vetting Card must carry, which the identity commitment is computed over, and which a counted statement must list as verified. Absent: none.";
|
|
1380
|
+
};
|
|
1381
|
+
readonly optionalClaims: {
|
|
1382
|
+
readonly type: "array";
|
|
1383
|
+
readonly uniqueItems: true;
|
|
1384
|
+
readonly items: {
|
|
1385
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
1386
|
+
};
|
|
1387
|
+
readonly description: "Claim types an applicant MAY add to the card and a vetter MAY verify. They never affect whether a statement counts.";
|
|
1388
|
+
};
|
|
1389
|
+
readonly maxStatementAge: {
|
|
1390
|
+
readonly $ref: "#/$defs/Duration";
|
|
1391
|
+
};
|
|
1392
|
+
readonly eligibleVetters: {
|
|
1393
|
+
readonly type: "object";
|
|
1394
|
+
readonly additionalProperties: false;
|
|
1395
|
+
readonly required: readonly ["role"];
|
|
1396
|
+
readonly properties: {
|
|
1397
|
+
readonly role: {
|
|
1398
|
+
readonly type: "string";
|
|
1399
|
+
readonly minLength: 1;
|
|
1400
|
+
readonly maxLength: 128;
|
|
1401
|
+
readonly pattern: "^[a-zA-Z][a-zA-Z0-9_-]*$";
|
|
1402
|
+
readonly description: "The role a statement's issuer must hold, matched as the action `role:<role>` in a Verifiable Authority Credential (`AuthorityCredential`) the community issued to that issuer, whose `authority.scope` is the community's DID (see `vtc/vetting/vetters/grant/0.1`). A statement counts only if its issuer holds such a credential.";
|
|
1403
|
+
};
|
|
1404
|
+
};
|
|
1405
|
+
readonly description: "How a vetter's eligibility is established.";
|
|
1406
|
+
};
|
|
1407
|
+
readonly independence: {
|
|
1408
|
+
readonly type: "object";
|
|
1409
|
+
readonly additionalProperties: false;
|
|
1410
|
+
readonly properties: {
|
|
1411
|
+
readonly maxByDeclaredRelationship: {
|
|
1412
|
+
readonly type: "object";
|
|
1413
|
+
readonly propertyNames: {
|
|
1414
|
+
readonly $ref: "#/$defs/VettingRelationship";
|
|
1415
|
+
};
|
|
1416
|
+
readonly additionalProperties: {
|
|
1417
|
+
readonly type: "integer";
|
|
1418
|
+
readonly minimum: 0;
|
|
1419
|
+
};
|
|
1420
|
+
readonly description: "The most counted statements that may come from vetters declaring each relationship — e.g. `{ \"family\": 0 }`.";
|
|
1421
|
+
};
|
|
1422
|
+
readonly requireConsistentIdentityCommitment: {
|
|
1423
|
+
readonly type: "boolean";
|
|
1424
|
+
readonly description: "When true, every counted statement must carry the same identity commitment — all vetters verified the same claimed identity. Absent: false.";
|
|
1425
|
+
};
|
|
1426
|
+
};
|
|
1427
|
+
readonly description: "Caps on how much evidence may come from people close to the applicant. Absent: no caps.";
|
|
1428
|
+
};
|
|
1429
|
+
readonly invitation: {
|
|
1430
|
+
readonly type: "string";
|
|
1431
|
+
readonly enum: readonly ["required", "optional", "none"];
|
|
1432
|
+
readonly description: "Whether an invitation credential must accompany the statements at submission (`required`), may (`optional`), or plays no part (`none`). Absent: the presentation-definition alone governs.";
|
|
1433
|
+
};
|
|
1434
|
+
readonly decisionSla: {
|
|
1435
|
+
readonly $ref: "#/$defs/Duration";
|
|
1436
|
+
};
|
|
1437
|
+
readonly requirementsGrace: {
|
|
1438
|
+
readonly $ref: "#/$defs/Duration";
|
|
1439
|
+
};
|
|
1440
|
+
readonly governanceFrameworkUrl: {
|
|
1441
|
+
readonly type: "string";
|
|
1442
|
+
readonly format: "uri";
|
|
1443
|
+
readonly pattern: "^https://";
|
|
1444
|
+
readonly maxLength: 2048;
|
|
1445
|
+
readonly description: "Where the community's vetting governance — including the attestation text vetters sign — is published.";
|
|
1446
|
+
};
|
|
1447
|
+
readonly ext: {
|
|
1448
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1, for vetting parameters this version does not enumerate. A community publishing an admission mode the base members cannot express — the zero-knowledge parameters an applicant proves against, say — puts them under a namespace it controls, rather than waiting for a version that names them.\n\nThis object is already `additionalProperties: true`, so an unknown member here has always validated. That is not the same as reaching a consumer: a generated type names the members this schema declares and drops the rest, so an undeclared member is parsed and discarded, and it is discarded again on the re-serialization `requirementsDigest` is computed over. `ext` is a declared member, so it survives both.";
|
|
1449
|
+
readonly $ref: "#/$defs/Ext";
|
|
1450
|
+
};
|
|
1451
|
+
readonly extCritical: {
|
|
1452
|
+
readonly description: "Namespaces of `ext` an applicant MUST understand or refuse, per SPEC.md §4.5.1.\n\nA community marks a namespace here when applying under this criterion without understanding it would mean something other than what the community requires — an applicant that ignored a hidden-vetting namespace, for instance, would submit named statements to a criterion whose whole point was that it does not receive them. An applicant that does not recognize a marked namespace stops rather than downgrading silently.\n\nAbsent, which is the common case, every namespace under `ext` is advisory and ignorable.";
|
|
1453
|
+
readonly $ref: "#/$defs/ExtCritical";
|
|
1454
|
+
};
|
|
1455
|
+
};
|
|
1456
|
+
};
|
|
1457
|
+
readonly CommunityBranding: {
|
|
1458
|
+
readonly title: "CommunityBranding";
|
|
1459
|
+
readonly type: "object";
|
|
1460
|
+
readonly additionalProperties: false;
|
|
1461
|
+
readonly description: "OPTIONAL. How the community asks to be shown to a prospective applicant: a name, an accent colour and a logo. Presentation only, self-asserted and unverified — `communityDid` identifies the community, never `branding`. Not part of any criterion, so not covered by a `requirementsDigest`. Every member is optional.";
|
|
1462
|
+
readonly properties: {
|
|
1463
|
+
readonly displayName: {
|
|
1464
|
+
readonly type: "string";
|
|
1465
|
+
readonly minLength: 1;
|
|
1466
|
+
readonly maxLength: 128;
|
|
1467
|
+
readonly description: "The community's name as it asks to be shown.";
|
|
1468
|
+
};
|
|
1469
|
+
readonly accentColor: {
|
|
1470
|
+
readonly type: "string";
|
|
1471
|
+
readonly pattern: "^#[0-9a-fA-F]{6}$";
|
|
1472
|
+
readonly description: "An sRGB colour as `#rrggbb`, compared case-insensitively. A community SHOULD write it in lower case.";
|
|
1473
|
+
};
|
|
1474
|
+
readonly logoUrl: {
|
|
1475
|
+
readonly type: "string";
|
|
1476
|
+
readonly format: "uri";
|
|
1477
|
+
readonly pattern: "^https://";
|
|
1478
|
+
readonly maxLength: 2048;
|
|
1479
|
+
readonly description: "An https URL of the community's logo. Fetched by the client, so an untrusted image from wherever it points.";
|
|
1480
|
+
};
|
|
1481
|
+
readonly ext: {
|
|
1482
|
+
readonly $ref: "#/$defs/Ext";
|
|
1483
|
+
};
|
|
1484
|
+
};
|
|
1485
|
+
};
|
|
1486
|
+
readonly Response: {
|
|
1487
|
+
readonly $anchor: "response";
|
|
1488
|
+
readonly title: "VTC Join-Requests Manifest — response payload";
|
|
1489
|
+
readonly type: "object";
|
|
1490
|
+
readonly additionalProperties: false;
|
|
1491
|
+
readonly required: readonly ["communityDid", "criteria"];
|
|
1492
|
+
readonly properties: {
|
|
1493
|
+
readonly communityDid: {
|
|
1494
|
+
readonly type: "string";
|
|
1495
|
+
readonly pattern: "^did:";
|
|
1496
|
+
};
|
|
1497
|
+
readonly criteria: {
|
|
1498
|
+
readonly type: "array";
|
|
1499
|
+
readonly items: {
|
|
1500
|
+
readonly $ref: "#/$defs/Criterion";
|
|
1501
|
+
};
|
|
1502
|
+
};
|
|
1503
|
+
readonly requestedAttributes: {
|
|
1504
|
+
readonly type: "array";
|
|
1505
|
+
readonly maxItems: 32;
|
|
1506
|
+
readonly description: "What the community asks an applicant to tell it about themselves, as claim types — never values. Answered in persona terms: the applicant's agent discloses those attributes from the face the applicant chooses, and they arrive on vtc/join-requests/submit as `attributes`. SELF-ASSERTED: a community MUST NOT describe an answer as verified, and MUST NOT make a decision that assumes it is. Outside every criterion, so no `requirementsDigest` covers it. Absent when the community asks nothing.";
|
|
1507
|
+
readonly items: {
|
|
1508
|
+
readonly type: "object";
|
|
1509
|
+
readonly additionalProperties: false;
|
|
1510
|
+
readonly required: readonly ["type"];
|
|
1511
|
+
readonly properties: {
|
|
1512
|
+
readonly type: {
|
|
1513
|
+
readonly type: "string";
|
|
1514
|
+
readonly minLength: 1;
|
|
1515
|
+
readonly maxLength: 128;
|
|
1516
|
+
readonly pattern: "^(x:)?[a-z][A-Za-z0-9]*(\\.[a-z][A-Za-z0-9]*)*$";
|
|
1517
|
+
readonly description: "A claim-type token from the persona claim-type registry (persona/_shared/0.1/CLAIM-TYPES.md) — `name.display`, `address.country` — or an `x:` extension token.";
|
|
1518
|
+
};
|
|
1519
|
+
readonly required: {
|
|
1520
|
+
readonly type: "boolean";
|
|
1521
|
+
readonly default: true;
|
|
1522
|
+
readonly description: "False for an attribute the applicant may decline. A submission missing a required one is refused with vtc/join-requests/submit:attributesMissing.";
|
|
1523
|
+
};
|
|
1524
|
+
readonly purpose: {
|
|
1525
|
+
readonly type: "string";
|
|
1526
|
+
readonly maxLength: 256;
|
|
1527
|
+
readonly description: "Why the community asks, in words shown to the applicant before they disclose.";
|
|
1528
|
+
};
|
|
1529
|
+
};
|
|
1530
|
+
};
|
|
1531
|
+
};
|
|
1532
|
+
readonly branding: {
|
|
1533
|
+
readonly $ref: "#/$defs/CommunityBranding";
|
|
1534
|
+
};
|
|
1535
|
+
readonly directoryDisclosure: {
|
|
1536
|
+
readonly $ref: "#/$defs/DirectoryDisclosure";
|
|
1537
|
+
readonly description: "Present exactly where the community offers a member directory: the statement, generated from its configuration, of what the directory would disclose about a member and to whom — the same statement vtc/directory/disclosure returns. Outside every criterion, so no `requirementsDigest` covers it; it names itself with its own `statementDigest`.";
|
|
1538
|
+
};
|
|
1539
|
+
readonly ext: {
|
|
1540
|
+
readonly $ref: "#/$defs/Ext";
|
|
1541
|
+
};
|
|
1542
|
+
};
|
|
1543
|
+
};
|
|
1544
|
+
readonly Ext: {
|
|
1545
|
+
readonly title: "Ext";
|
|
1546
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
1547
|
+
readonly type: "object";
|
|
1548
|
+
readonly minProperties: 1;
|
|
1549
|
+
readonly additionalProperties: true;
|
|
1550
|
+
readonly propertyNames: {
|
|
1551
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
1552
|
+
};
|
|
1553
|
+
};
|
|
1554
|
+
readonly DirectoryDisclosure: {
|
|
1555
|
+
readonly title: "DirectoryDisclosure";
|
|
1556
|
+
readonly description: "The statement itself. Every member is generated from the community's configuration when the statement is read. `statementDigest` names this exact statement, so an applicant can record which one it was shown.";
|
|
1557
|
+
readonly type: "object";
|
|
1558
|
+
readonly additionalProperties: false;
|
|
1559
|
+
readonly required: readonly ["fields", "newCard", "membershipIdentifiers", "adminNotes", "externalCards", "statementDigest"];
|
|
1560
|
+
readonly properties: {
|
|
1561
|
+
readonly fields: {
|
|
1562
|
+
readonly type: "array";
|
|
1563
|
+
readonly maxItems: 128;
|
|
1564
|
+
readonly items: {
|
|
1565
|
+
readonly $ref: "#/$defs/DisclosedField";
|
|
1566
|
+
};
|
|
1567
|
+
readonly description: "Every active field, base and community-defined, in display order. A base field the community has disabled is absent, which is how a reader learns it is not collected.";
|
|
1568
|
+
};
|
|
1569
|
+
readonly newCard: {
|
|
1570
|
+
readonly $ref: "#/$defs/NewCardDefaults";
|
|
1571
|
+
};
|
|
1572
|
+
readonly membershipIdentifiers: {
|
|
1573
|
+
readonly $ref: "#/$defs/Audience";
|
|
1574
|
+
readonly description: "The widest audience a member's membership identifier — the DID they joined with — can reach through the directory: the ceiling of the base field `did`, or `admins` where that field is disabled. `members` or `public` means a member may choose to show it that widely; a new card never shows it beyond `admins` (VTI-DIR-042). Administrators always see it.";
|
|
1575
|
+
};
|
|
1576
|
+
readonly adminNotes: {
|
|
1577
|
+
readonly type: "boolean";
|
|
1578
|
+
readonly description: "Whether administrators keep notes about members. Notes are never on a card and never reach another member; a member may ask for the notes about them.";
|
|
1579
|
+
};
|
|
1580
|
+
readonly groups: {
|
|
1581
|
+
readonly $ref: "#/$defs/GroupDisclosure";
|
|
1582
|
+
};
|
|
1583
|
+
readonly externalCards: {
|
|
1584
|
+
readonly type: "boolean";
|
|
1585
|
+
readonly description: "Whether a member may publish a card beyond the community: their `public` values, signed by them, offered through the community's trust registry. Always the member's own choice, and off on a new card. False where the community cannot publish external cards.";
|
|
1586
|
+
};
|
|
1587
|
+
readonly statementDigest: {
|
|
1588
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
1589
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this statement with the `statementDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Changes exactly when what the statement says changes.";
|
|
1590
|
+
};
|
|
1591
|
+
readonly ext: {
|
|
1592
|
+
readonly $ref: "#/$defs/Ext";
|
|
1593
|
+
};
|
|
1594
|
+
};
|
|
1595
|
+
};
|
|
1596
|
+
readonly GroupDisclosure: {
|
|
1597
|
+
readonly title: "GroupDisclosure";
|
|
1598
|
+
readonly description: "Present when the community has groups. A member of a group holds a credential, issued by the group's own identifier, that evidences their membership, and can present it outside the community — which is why an applicant is told.";
|
|
1599
|
+
readonly type: "object";
|
|
1600
|
+
readonly additionalProperties: false;
|
|
1601
|
+
readonly required: readonly ["credentialValidity"];
|
|
1602
|
+
readonly properties: {
|
|
1603
|
+
readonly credentialValidity: {
|
|
1604
|
+
readonly type: "string";
|
|
1605
|
+
readonly maxLength: 32;
|
|
1606
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
1607
|
+
readonly description: "How long each group membership credential is valid for, as an ISO 8601 duration in weeks, days, hours, minutes and seconds (`P30D`). It is renewed while the member stays in the group, and a credential already issued stays valid until it expires even after its holder leaves.";
|
|
1608
|
+
};
|
|
1609
|
+
};
|
|
1610
|
+
};
|
|
1611
|
+
readonly NewCardDefaults: {
|
|
1612
|
+
readonly title: "NewCardDefaults";
|
|
1613
|
+
readonly description: "The discoverability a card has when the community creates it, before its member chooses. A new card is never published beyond the community (VTI-DIR-042), so there is no member for that here: `externalCards` says whether the member may turn it on.";
|
|
1614
|
+
readonly type: "object";
|
|
1615
|
+
readonly additionalProperties: false;
|
|
1616
|
+
readonly required: readonly ["listing", "search"];
|
|
1617
|
+
readonly properties: {
|
|
1618
|
+
readonly listing: {
|
|
1619
|
+
readonly $ref: "#/$defs/Listing";
|
|
1620
|
+
readonly description: "The listing a new card starts with: the community's `defaultListing` (vtc/directory/fields/list). Every member may always choose `hidden`.";
|
|
1621
|
+
};
|
|
1622
|
+
readonly search: {
|
|
1623
|
+
readonly type: "string";
|
|
1624
|
+
readonly enum: readonly ["byName", "exactNickname", "off"];
|
|
1625
|
+
readonly description: "What a member's search may match, as the card's `discoverability.search`.";
|
|
1626
|
+
};
|
|
1627
|
+
readonly introductions: {
|
|
1628
|
+
readonly $ref: "#/$defs/Introductions";
|
|
1629
|
+
readonly description: "From whom a new card accepts introductions. Absent where the community does not deliver introductions.";
|
|
1630
|
+
};
|
|
1631
|
+
};
|
|
1632
|
+
};
|
|
1633
|
+
readonly Introductions: {
|
|
1634
|
+
readonly title: "Introductions";
|
|
1635
|
+
readonly description: "Who may ask the community to introduce them to this member. `anyone`: any active member who can find the entry. `groups`: only members who share a community group with them. `connections`: only members holding an attributed, in-force verified relationship with them. `off`: nobody. A refused introduction is never reported to its sender.";
|
|
1636
|
+
readonly type: "string";
|
|
1637
|
+
readonly enum: readonly ["anyone", "groups", "connections", "off"];
|
|
1638
|
+
};
|
|
1639
|
+
readonly Listing: {
|
|
1640
|
+
readonly title: "Listing";
|
|
1641
|
+
readonly description: "Whether members can find the entry. `listed`: it appears when members browse. `findable`: it does not appear when browsing, but a search that matches it under `search` returns it. `hidden`: no member finds it by browsing or searching; administrators still see it, and members who share a group that shows its members see it in that group's member list.";
|
|
1642
|
+
readonly type: "string";
|
|
1643
|
+
readonly enum: readonly ["listed", "findable", "hidden"];
|
|
1644
|
+
};
|
|
1645
|
+
readonly DisclosedField: {
|
|
1646
|
+
readonly title: "DisclosedField";
|
|
1647
|
+
readonly description: "One active field of the community's directory, as an applicant needs to see it: what it is, who writes its value, the widest audience it may ever reach and the audience a new card gives it. Disabled and retired fields are not listed: no projection shows them.";
|
|
1648
|
+
readonly type: "object";
|
|
1649
|
+
readonly additionalProperties: false;
|
|
1650
|
+
readonly required: readonly ["key", "label", "type", "source", "ceiling", "defaultVisibility", "searchable"];
|
|
1651
|
+
readonly properties: {
|
|
1652
|
+
readonly key: {
|
|
1653
|
+
readonly $ref: "#/$defs/FieldKey";
|
|
1654
|
+
};
|
|
1655
|
+
readonly label: {
|
|
1656
|
+
readonly $ref: "#/$defs/FieldLabel";
|
|
1657
|
+
};
|
|
1658
|
+
readonly description: {
|
|
1659
|
+
readonly $ref: "#/$defs/FieldDescription";
|
|
1660
|
+
};
|
|
1661
|
+
readonly type: {
|
|
1662
|
+
readonly $ref: "#/$defs/FieldType";
|
|
1663
|
+
};
|
|
1664
|
+
readonly source: {
|
|
1665
|
+
readonly $ref: "#/$defs/FieldSource";
|
|
1666
|
+
readonly description: "Who writes the value. `admin` and `credential` matter most to an applicant: an `admin` field holds what the community asserts about the member, which the member reads and cannot change.";
|
|
1667
|
+
};
|
|
1668
|
+
readonly ceiling: {
|
|
1669
|
+
readonly $ref: "#/$defs/Audience";
|
|
1670
|
+
readonly description: "The widest audience the field may ever reach, whatever the member chooses.";
|
|
1671
|
+
};
|
|
1672
|
+
readonly defaultVisibility: {
|
|
1673
|
+
readonly $ref: "#/$defs/Audience";
|
|
1674
|
+
readonly description: "The audience a new card gives the field until its member chooses. Never wider than `ceiling`.";
|
|
1675
|
+
};
|
|
1676
|
+
readonly searchable: {
|
|
1677
|
+
readonly type: "boolean";
|
|
1678
|
+
readonly description: "Whether a member's search may match the field, within what the searcher may see.";
|
|
1679
|
+
};
|
|
1680
|
+
readonly facet: {
|
|
1681
|
+
readonly type: "boolean";
|
|
1682
|
+
readonly description: "Whether members may filter on the field and see counts by its values. Absent: false.";
|
|
1683
|
+
};
|
|
1684
|
+
};
|
|
1685
|
+
};
|
|
1686
|
+
readonly Audience: {
|
|
1687
|
+
readonly title: "Audience";
|
|
1688
|
+
readonly description: "Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\n\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.";
|
|
1689
|
+
readonly type: "string";
|
|
1690
|
+
readonly enum: readonly ["admins", "groups", "connections", "members", "public"];
|
|
1691
|
+
};
|
|
1692
|
+
readonly FieldSource: {
|
|
1693
|
+
readonly title: "FieldSource";
|
|
1694
|
+
readonly description: "Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.";
|
|
1695
|
+
readonly type: "string";
|
|
1696
|
+
readonly enum: readonly ["member", "admin", "credential", "derived"];
|
|
1697
|
+
};
|
|
1698
|
+
readonly FieldType: {
|
|
1699
|
+
readonly title: "FieldType";
|
|
1700
|
+
readonly description: "The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.";
|
|
1701
|
+
readonly type: "string";
|
|
1702
|
+
readonly enum: readonly ["text", "longText", "url", "email", "phone", "enum", "multiEnum", "date", "country", "image", "did", "claim"];
|
|
1703
|
+
};
|
|
1704
|
+
readonly FieldDescription: {
|
|
1705
|
+
readonly title: "FieldDescription";
|
|
1706
|
+
readonly type: "string";
|
|
1707
|
+
readonly minLength: 1;
|
|
1708
|
+
readonly maxLength: 280;
|
|
1709
|
+
readonly description: "Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.";
|
|
1710
|
+
};
|
|
1711
|
+
readonly FieldLabel: {
|
|
1712
|
+
readonly title: "FieldLabel";
|
|
1713
|
+
readonly type: "string";
|
|
1714
|
+
readonly minLength: 1;
|
|
1715
|
+
readonly maxLength: 64;
|
|
1716
|
+
readonly description: "What readers see as the field's name. Plain text.";
|
|
1717
|
+
};
|
|
1718
|
+
readonly FieldKey: {
|
|
1719
|
+
readonly title: "FieldKey";
|
|
1720
|
+
readonly description: "Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.";
|
|
1721
|
+
readonly type: "string";
|
|
1722
|
+
readonly minLength: 1;
|
|
1723
|
+
readonly maxLength: 128;
|
|
1724
|
+
readonly pattern: "^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$";
|
|
1725
|
+
};
|
|
1726
|
+
readonly DigestMultibase: {
|
|
1727
|
+
readonly title: "DigestMultibase";
|
|
1728
|
+
readonly description: "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.";
|
|
1729
|
+
readonly type: "string";
|
|
1730
|
+
readonly minLength: 16;
|
|
1731
|
+
readonly pattern: "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$";
|
|
1732
|
+
readonly examples: readonly ["zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"];
|
|
1733
|
+
};
|
|
1734
|
+
readonly ExtCritical: {
|
|
1735
|
+
readonly title: "ExtCritical";
|
|
1736
|
+
readonly description: "Names the `ext` namespaces a consumer MUST understand or refuse, per SPEC.md §4.5.1.\n\nEvery entry MUST be an immediate key of the sibling `ext` object at the same level; an entry naming an absent namespace is non-conforming and the consumer rejects the document with `malformedRequest`. A consumer that does not recognize a namespace named here MUST NOT process the document as though the namespace were absent, and rejects it with `unsupportedExtension` — the exception to the rule that unrecognized namespaces are ignored.\n\nA producer marks a namespace only where the document's meaning depends on it. Marking one that merely carries a hint or an annotation turns every consumer that has not implemented it into a failure where it would otherwise have interoperated. JSON Schema cannot check either of those rules: that an entry names a present namespace is checkable only against the sibling `ext`, and whether a namespace is load-bearing is not a schema question at all. Both are consumer-side checks.";
|
|
1737
|
+
readonly type: "array";
|
|
1738
|
+
readonly minItems: 1;
|
|
1739
|
+
readonly uniqueItems: true;
|
|
1740
|
+
readonly items: {
|
|
1741
|
+
readonly type: "string";
|
|
1742
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
1743
|
+
};
|
|
1744
|
+
readonly examples: readonly [readonly ["org.openvtc.hidden-vetting"]];
|
|
1745
|
+
};
|
|
1746
|
+
readonly VettingRelationship: {
|
|
1747
|
+
readonly title: "VettingRelationship";
|
|
1748
|
+
readonly type: "string";
|
|
1749
|
+
readonly enum: readonly ["none", "communityColleague", "sameEmployer", "family", "otherPersonal"];
|
|
1750
|
+
readonly description: "The vetter's own declaration of how they relate to the applicant. Declared, not verified: it exists so community policy can cap how much evidence comes from people close to the applicant, and a false declaration is the vetter's attributable act.";
|
|
1751
|
+
};
|
|
1752
|
+
readonly ClaimType: {
|
|
1753
|
+
readonly title: "ClaimType";
|
|
1754
|
+
readonly description: "The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\n\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\n\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.";
|
|
1755
|
+
readonly type: "string";
|
|
1756
|
+
readonly minLength: 1;
|
|
1757
|
+
readonly maxLength: 128;
|
|
1758
|
+
readonly pattern: "^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$";
|
|
1759
|
+
};
|
|
1760
|
+
readonly VettingDocumentation: {
|
|
1761
|
+
readonly title: "VettingDocumentation";
|
|
1762
|
+
readonly type: "string";
|
|
1763
|
+
readonly minLength: 1;
|
|
1764
|
+
readonly maxLength: 64;
|
|
1765
|
+
readonly pattern: "^[a-z][a-zA-Z0-9]*$";
|
|
1766
|
+
readonly description: "A class of documentation, named in lowerCamelCase. Open rather than enumerated, because what documentation a vetter accepts is each vetter's own choice. Well-known values: `passport`, `nationalId`, `driverLicence`, and `none` — the vetter will attest without a document, which is the `priorAcquaintance` case. Only the class ever travels — never a document number, an image, an issuing authority or an expiry date. `none` states a policy (what a vetter accepts); a record of what was relied on expresses 'no document' as an empty list instead.";
|
|
1767
|
+
};
|
|
1768
|
+
readonly VettingMethod: {
|
|
1769
|
+
readonly title: "VettingMethod";
|
|
1770
|
+
readonly type: "string";
|
|
1771
|
+
readonly enum: readonly ["inPerson", "video", "priorAcquaintance"];
|
|
1772
|
+
readonly description: "How the vetter established that the person they checked is the person controlling the applicant's DID. `inPerson` — both people were physically together. `video` — a live, two-way video call. `priorAcquaintance` — the vetter has known or worked with this person over a period, and attests from that knowledge rather than from a document. A method is a description of what happened, not an assurance level: which methods count, and how many of each, is community policy.";
|
|
1773
|
+
};
|
|
1774
|
+
};
|
|
1775
|
+
};
|
|
1776
|
+
};
|
|
1777
|
+
/**
|
|
1778
|
+
* SPEC.md §7.2 policy for the success-response variant. `isRecipientRequired`
|
|
1779
|
+
* tracks the *issuer* party's requirement because a response swaps the
|
|
1780
|
+
* parties (§7.3 item 5).
|
|
1781
|
+
*/
|
|
1782
|
+
export declare const RESPONSE_SPEC: {
|
|
1783
|
+
readonly typeUri: "https://trusttasks.org/spec/vtc/join-requests/manifest/0.4#response";
|
|
1784
|
+
readonly isBearer: false;
|
|
1785
|
+
readonly isProofRequired: false;
|
|
1786
|
+
readonly isRecipientRequired: true;
|
|
1787
|
+
readonly isIssuedAtRequired: false;
|
|
1788
|
+
readonly payloadSchema: {
|
|
1789
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
1790
|
+
readonly $ref: "#/$defs/Response";
|
|
1791
|
+
readonly $defs: {
|
|
1792
|
+
readonly Duration: {
|
|
1793
|
+
readonly title: "Duration";
|
|
1794
|
+
readonly type: "string";
|
|
1795
|
+
readonly maxLength: 32;
|
|
1796
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
1797
|
+
readonly description: "An ISO 8601 duration in weeks, days, hours, minutes and seconds only (e.g. `P120D`, `P2W`, `P1DT12H`, `PT15M`). Years and months are refused: their length depends on the calendar, and an age limit that means different things on different days is not a limit.";
|
|
1798
|
+
};
|
|
1799
|
+
readonly Criterion: {
|
|
1800
|
+
readonly title: "Criterion";
|
|
1801
|
+
readonly type: "object";
|
|
1802
|
+
readonly additionalProperties: false;
|
|
1803
|
+
readonly required: readonly ["id", "admission", "requirementsDigest"];
|
|
1804
|
+
readonly properties: {
|
|
1805
|
+
readonly id: {
|
|
1806
|
+
readonly type: "string";
|
|
1807
|
+
readonly minLength: 1;
|
|
1808
|
+
readonly maxLength: 128;
|
|
1809
|
+
};
|
|
1810
|
+
readonly description: {
|
|
1811
|
+
readonly type: "string";
|
|
1812
|
+
readonly maxLength: 1024;
|
|
1813
|
+
readonly description: "Plain-language summary of the criterion, authored by the community and shown to prospective applicants. Informative: where it and `vetting` disagree, `vetting` governs.";
|
|
1814
|
+
};
|
|
1815
|
+
readonly admission: {
|
|
1816
|
+
readonly type: "string";
|
|
1817
|
+
readonly enum: readonly ["automatic", "review"];
|
|
1818
|
+
readonly description: "How the community decides a submission that meets this criterion. `automatic`: it admits the applicant without a person deciding. `review`: it refers the submission to an administrator, who decides.";
|
|
1819
|
+
};
|
|
1820
|
+
readonly presentationDefinition: {
|
|
1821
|
+
readonly type: "object";
|
|
1822
|
+
readonly description: "The credentials an applicant must present for this criterion (opaque here). Absent: the criterion requires no credential.";
|
|
1823
|
+
};
|
|
1824
|
+
readonly credentialIssuers: {
|
|
1825
|
+
readonly type: "string";
|
|
1826
|
+
readonly enum: readonly ["any", "community", "recognised"];
|
|
1827
|
+
readonly description: "Whose credentials meet `presentationDefinition`: `community` (this community's own), `recognised` (this community's, or a community it recognises), or `any` (any issuer whose credential verifies). Present exactly when `presentationDefinition` is.";
|
|
1828
|
+
};
|
|
1829
|
+
readonly invitationRequired: {
|
|
1830
|
+
readonly type: "boolean";
|
|
1831
|
+
readonly description: "True: the criterion is met only by a submission carrying a valid, unconsumed invitation this community issued to the applicant.";
|
|
1832
|
+
};
|
|
1833
|
+
readonly vetting: {
|
|
1834
|
+
readonly $ref: "#/$defs/VettingRequirements";
|
|
1835
|
+
};
|
|
1836
|
+
readonly requirementsDigest: {
|
|
1837
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
1838
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this criterion object with the `requirementsDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Names one version of the criterion: an applicant records it when starting an application and echoes it to vetters and at submission.";
|
|
1839
|
+
};
|
|
1840
|
+
};
|
|
1841
|
+
readonly dependentRequired: {
|
|
1842
|
+
readonly presentationDefinition: readonly ["credentialIssuers"];
|
|
1843
|
+
readonly credentialIssuers: readonly ["presentationDefinition"];
|
|
1844
|
+
};
|
|
1845
|
+
};
|
|
1846
|
+
readonly VettingRequirements: {
|
|
1847
|
+
readonly title: "VettingRequirements";
|
|
1848
|
+
readonly type: "object";
|
|
1849
|
+
readonly additionalProperties: true;
|
|
1850
|
+
readonly required: readonly ["version", "statementType", "minStatements", "acceptedMethods", "eligibleVetters"];
|
|
1851
|
+
readonly description: "What identity-vetting evidence a criterion needs, beyond what a presentation-definition can express: distinct eligible vetters, per-method floors, independence caps. Every number is the community's own policy. This schema supplies no defaults — an absent optional member means the community imposes no constraint of that kind, never that some protocol value applies. Deliberately open: a consumer MUST ignore members it does not recognise, so a community publishing a newer shape does not make an older client unable to read the rest. Durations: `maxStatementAge` — a statement older than this at decision time does not count (absent: no limit beyond the statement's own validity); `decisionSla` — how long after submission the community undertakes to decide, including on a referred application; `requirementsGrace` — how long an application started under an earlier `requirementsDigest` is still evaluated under that version.";
|
|
1852
|
+
readonly properties: {
|
|
1853
|
+
readonly version: {
|
|
1854
|
+
readonly type: "string";
|
|
1855
|
+
readonly pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$";
|
|
1856
|
+
readonly description: "Version of this requirements object's shape. `0.1` for the members defined here.";
|
|
1857
|
+
};
|
|
1858
|
+
readonly statementType: {
|
|
1859
|
+
readonly type: "string";
|
|
1860
|
+
readonly format: "uri";
|
|
1861
|
+
readonly minLength: 1;
|
|
1862
|
+
readonly maxLength: 512;
|
|
1863
|
+
readonly description: "The predicate IRI a counted vetting statement carries in `credentialSubject.predicate` — `https://registry.trustoverip.org/dtg/vsc/vetted/1`, the DTG VSC registry's identity-vetting predicate, or a predicate in a namespace the community controls — registered as one the community accepts via vtc/endorsement-types/register. A statement under any other predicate does not count.";
|
|
1864
|
+
};
|
|
1865
|
+
readonly minStatements: {
|
|
1866
|
+
readonly type: "integer";
|
|
1867
|
+
readonly minimum: 1;
|
|
1868
|
+
readonly description: "How many counted statements are needed, counting each vetter once however many DIDs they hold.";
|
|
1869
|
+
};
|
|
1870
|
+
readonly minByMethod: {
|
|
1871
|
+
readonly type: "object";
|
|
1872
|
+
readonly propertyNames: {
|
|
1873
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
1874
|
+
};
|
|
1875
|
+
readonly additionalProperties: {
|
|
1876
|
+
readonly type: "integer";
|
|
1877
|
+
readonly minimum: 0;
|
|
1878
|
+
};
|
|
1879
|
+
readonly description: "Per-method floors within `minStatements` — e.g. `{ \"inPerson\": 1 }`. Every method named MUST also be in `acceptedMethods`. Absent: no method floor.";
|
|
1880
|
+
};
|
|
1881
|
+
readonly acceptedMethods: {
|
|
1882
|
+
readonly type: "array";
|
|
1883
|
+
readonly minItems: 1;
|
|
1884
|
+
readonly uniqueItems: true;
|
|
1885
|
+
readonly items: {
|
|
1886
|
+
readonly $ref: "#/$defs/VettingMethod";
|
|
1887
|
+
};
|
|
1888
|
+
readonly description: "Methods whose statements count at all.";
|
|
1889
|
+
};
|
|
1890
|
+
readonly acceptedDocumentClasses: {
|
|
1891
|
+
readonly type: "array";
|
|
1892
|
+
readonly minItems: 1;
|
|
1893
|
+
readonly uniqueItems: true;
|
|
1894
|
+
readonly items: {
|
|
1895
|
+
readonly $ref: "#/$defs/VettingDocumentation";
|
|
1896
|
+
};
|
|
1897
|
+
readonly description: "Documentation a statement must have relied on in order to count. Absent — the expected case — means each vetter decides what documentation they accept, including none for prior acquaintance, and the community counts what they attest.";
|
|
1898
|
+
};
|
|
1899
|
+
readonly requiredClaims: {
|
|
1900
|
+
readonly type: "array";
|
|
1901
|
+
readonly uniqueItems: true;
|
|
1902
|
+
readonly items: {
|
|
1903
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
1904
|
+
};
|
|
1905
|
+
readonly description: "Claim types the applicant's Vetting Card must carry, which the identity commitment is computed over, and which a counted statement must list as verified. Absent: none.";
|
|
1906
|
+
};
|
|
1907
|
+
readonly optionalClaims: {
|
|
1908
|
+
readonly type: "array";
|
|
1909
|
+
readonly uniqueItems: true;
|
|
1910
|
+
readonly items: {
|
|
1911
|
+
readonly $ref: "#/$defs/ClaimType";
|
|
1912
|
+
};
|
|
1913
|
+
readonly description: "Claim types an applicant MAY add to the card and a vetter MAY verify. They never affect whether a statement counts.";
|
|
1914
|
+
};
|
|
1915
|
+
readonly maxStatementAge: {
|
|
1916
|
+
readonly $ref: "#/$defs/Duration";
|
|
1917
|
+
};
|
|
1918
|
+
readonly eligibleVetters: {
|
|
1919
|
+
readonly type: "object";
|
|
1920
|
+
readonly additionalProperties: false;
|
|
1921
|
+
readonly required: readonly ["role"];
|
|
1922
|
+
readonly properties: {
|
|
1923
|
+
readonly role: {
|
|
1924
|
+
readonly type: "string";
|
|
1925
|
+
readonly minLength: 1;
|
|
1926
|
+
readonly maxLength: 128;
|
|
1927
|
+
readonly pattern: "^[a-zA-Z][a-zA-Z0-9_-]*$";
|
|
1928
|
+
readonly description: "The role a statement's issuer must hold, matched as the action `role:<role>` in a Verifiable Authority Credential (`AuthorityCredential`) the community issued to that issuer, whose `authority.scope` is the community's DID (see `vtc/vetting/vetters/grant/0.1`). A statement counts only if its issuer holds such a credential.";
|
|
1929
|
+
};
|
|
1930
|
+
};
|
|
1931
|
+
readonly description: "How a vetter's eligibility is established.";
|
|
1932
|
+
};
|
|
1933
|
+
readonly independence: {
|
|
1934
|
+
readonly type: "object";
|
|
1935
|
+
readonly additionalProperties: false;
|
|
1936
|
+
readonly properties: {
|
|
1937
|
+
readonly maxByDeclaredRelationship: {
|
|
1938
|
+
readonly type: "object";
|
|
1939
|
+
readonly propertyNames: {
|
|
1940
|
+
readonly $ref: "#/$defs/VettingRelationship";
|
|
1941
|
+
};
|
|
1942
|
+
readonly additionalProperties: {
|
|
1943
|
+
readonly type: "integer";
|
|
1944
|
+
readonly minimum: 0;
|
|
1945
|
+
};
|
|
1946
|
+
readonly description: "The most counted statements that may come from vetters declaring each relationship — e.g. `{ \"family\": 0 }`.";
|
|
1947
|
+
};
|
|
1948
|
+
readonly requireConsistentIdentityCommitment: {
|
|
1949
|
+
readonly type: "boolean";
|
|
1950
|
+
readonly description: "When true, every counted statement must carry the same identity commitment — all vetters verified the same claimed identity. Absent: false.";
|
|
1951
|
+
};
|
|
1952
|
+
};
|
|
1953
|
+
readonly description: "Caps on how much evidence may come from people close to the applicant. Absent: no caps.";
|
|
1954
|
+
};
|
|
1955
|
+
readonly invitation: {
|
|
1956
|
+
readonly type: "string";
|
|
1957
|
+
readonly enum: readonly ["required", "optional", "none"];
|
|
1958
|
+
readonly description: "Whether an invitation credential must accompany the statements at submission (`required`), may (`optional`), or plays no part (`none`). Absent: the presentation-definition alone governs.";
|
|
1959
|
+
};
|
|
1960
|
+
readonly decisionSla: {
|
|
1961
|
+
readonly $ref: "#/$defs/Duration";
|
|
1962
|
+
};
|
|
1963
|
+
readonly requirementsGrace: {
|
|
1964
|
+
readonly $ref: "#/$defs/Duration";
|
|
1965
|
+
};
|
|
1966
|
+
readonly governanceFrameworkUrl: {
|
|
1967
|
+
readonly type: "string";
|
|
1968
|
+
readonly format: "uri";
|
|
1969
|
+
readonly pattern: "^https://";
|
|
1970
|
+
readonly maxLength: 2048;
|
|
1971
|
+
readonly description: "Where the community's vetting governance — including the attestation text vetters sign — is published.";
|
|
1972
|
+
};
|
|
1973
|
+
readonly ext: {
|
|
1974
|
+
readonly description: "Ecosystem-defined extension members per SPEC.md §4.5.1, for vetting parameters this version does not enumerate. A community publishing an admission mode the base members cannot express — the zero-knowledge parameters an applicant proves against, say — puts them under a namespace it controls, rather than waiting for a version that names them.\n\nThis object is already `additionalProperties: true`, so an unknown member here has always validated. That is not the same as reaching a consumer: a generated type names the members this schema declares and drops the rest, so an undeclared member is parsed and discarded, and it is discarded again on the re-serialization `requirementsDigest` is computed over. `ext` is a declared member, so it survives both.";
|
|
1975
|
+
readonly $ref: "#/$defs/Ext";
|
|
1976
|
+
};
|
|
1977
|
+
readonly extCritical: {
|
|
1978
|
+
readonly description: "Namespaces of `ext` an applicant MUST understand or refuse, per SPEC.md §4.5.1.\n\nA community marks a namespace here when applying under this criterion without understanding it would mean something other than what the community requires — an applicant that ignored a hidden-vetting namespace, for instance, would submit named statements to a criterion whose whole point was that it does not receive them. An applicant that does not recognize a marked namespace stops rather than downgrading silently.\n\nAbsent, which is the common case, every namespace under `ext` is advisory and ignorable.";
|
|
1979
|
+
readonly $ref: "#/$defs/ExtCritical";
|
|
1980
|
+
};
|
|
1981
|
+
};
|
|
1982
|
+
};
|
|
1983
|
+
readonly CommunityBranding: {
|
|
1984
|
+
readonly title: "CommunityBranding";
|
|
1985
|
+
readonly type: "object";
|
|
1986
|
+
readonly additionalProperties: false;
|
|
1987
|
+
readonly description: "OPTIONAL. How the community asks to be shown to a prospective applicant: a name, an accent colour and a logo. Presentation only, self-asserted and unverified — `communityDid` identifies the community, never `branding`. Not part of any criterion, so not covered by a `requirementsDigest`. Every member is optional.";
|
|
1988
|
+
readonly properties: {
|
|
1989
|
+
readonly displayName: {
|
|
1990
|
+
readonly type: "string";
|
|
1991
|
+
readonly minLength: 1;
|
|
1992
|
+
readonly maxLength: 128;
|
|
1993
|
+
readonly description: "The community's name as it asks to be shown.";
|
|
1994
|
+
};
|
|
1995
|
+
readonly accentColor: {
|
|
1996
|
+
readonly type: "string";
|
|
1997
|
+
readonly pattern: "^#[0-9a-fA-F]{6}$";
|
|
1998
|
+
readonly description: "An sRGB colour as `#rrggbb`, compared case-insensitively. A community SHOULD write it in lower case.";
|
|
1999
|
+
};
|
|
2000
|
+
readonly logoUrl: {
|
|
2001
|
+
readonly type: "string";
|
|
2002
|
+
readonly format: "uri";
|
|
2003
|
+
readonly pattern: "^https://";
|
|
2004
|
+
readonly maxLength: 2048;
|
|
2005
|
+
readonly description: "An https URL of the community's logo. Fetched by the client, so an untrusted image from wherever it points.";
|
|
2006
|
+
};
|
|
2007
|
+
readonly ext: {
|
|
2008
|
+
readonly $ref: "#/$defs/Ext";
|
|
2009
|
+
};
|
|
2010
|
+
};
|
|
2011
|
+
};
|
|
2012
|
+
readonly Response: {
|
|
2013
|
+
readonly $anchor: "response";
|
|
2014
|
+
readonly title: "VTC Join-Requests Manifest — response payload";
|
|
2015
|
+
readonly type: "object";
|
|
2016
|
+
readonly additionalProperties: false;
|
|
2017
|
+
readonly required: readonly ["communityDid", "criteria"];
|
|
2018
|
+
readonly properties: {
|
|
2019
|
+
readonly communityDid: {
|
|
2020
|
+
readonly type: "string";
|
|
2021
|
+
readonly pattern: "^did:";
|
|
2022
|
+
};
|
|
2023
|
+
readonly criteria: {
|
|
2024
|
+
readonly type: "array";
|
|
2025
|
+
readonly items: {
|
|
2026
|
+
readonly $ref: "#/$defs/Criterion";
|
|
2027
|
+
};
|
|
2028
|
+
};
|
|
2029
|
+
readonly requestedAttributes: {
|
|
2030
|
+
readonly type: "array";
|
|
2031
|
+
readonly maxItems: 32;
|
|
2032
|
+
readonly description: "What the community asks an applicant to tell it about themselves, as claim types — never values. Answered in persona terms: the applicant's agent discloses those attributes from the face the applicant chooses, and they arrive on vtc/join-requests/submit as `attributes`. SELF-ASSERTED: a community MUST NOT describe an answer as verified, and MUST NOT make a decision that assumes it is. Outside every criterion, so no `requirementsDigest` covers it. Absent when the community asks nothing.";
|
|
2033
|
+
readonly items: {
|
|
2034
|
+
readonly type: "object";
|
|
2035
|
+
readonly additionalProperties: false;
|
|
2036
|
+
readonly required: readonly ["type"];
|
|
2037
|
+
readonly properties: {
|
|
2038
|
+
readonly type: {
|
|
2039
|
+
readonly type: "string";
|
|
2040
|
+
readonly minLength: 1;
|
|
2041
|
+
readonly maxLength: 128;
|
|
2042
|
+
readonly pattern: "^(x:)?[a-z][A-Za-z0-9]*(\\.[a-z][A-Za-z0-9]*)*$";
|
|
2043
|
+
readonly description: "A claim-type token from the persona claim-type registry (persona/_shared/0.1/CLAIM-TYPES.md) — `name.display`, `address.country` — or an `x:` extension token.";
|
|
2044
|
+
};
|
|
2045
|
+
readonly required: {
|
|
2046
|
+
readonly type: "boolean";
|
|
2047
|
+
readonly default: true;
|
|
2048
|
+
readonly description: "False for an attribute the applicant may decline. A submission missing a required one is refused with vtc/join-requests/submit:attributesMissing.";
|
|
2049
|
+
};
|
|
2050
|
+
readonly purpose: {
|
|
2051
|
+
readonly type: "string";
|
|
2052
|
+
readonly maxLength: 256;
|
|
2053
|
+
readonly description: "Why the community asks, in words shown to the applicant before they disclose.";
|
|
2054
|
+
};
|
|
2055
|
+
};
|
|
2056
|
+
};
|
|
2057
|
+
};
|
|
2058
|
+
readonly branding: {
|
|
2059
|
+
readonly $ref: "#/$defs/CommunityBranding";
|
|
2060
|
+
};
|
|
2061
|
+
readonly directoryDisclosure: {
|
|
2062
|
+
readonly $ref: "#/$defs/DirectoryDisclosure";
|
|
2063
|
+
readonly description: "Present exactly where the community offers a member directory: the statement, generated from its configuration, of what the directory would disclose about a member and to whom — the same statement vtc/directory/disclosure returns. Outside every criterion, so no `requirementsDigest` covers it; it names itself with its own `statementDigest`.";
|
|
2064
|
+
};
|
|
2065
|
+
readonly ext: {
|
|
2066
|
+
readonly $ref: "#/$defs/Ext";
|
|
2067
|
+
};
|
|
2068
|
+
};
|
|
2069
|
+
};
|
|
2070
|
+
readonly Ext: {
|
|
2071
|
+
readonly title: "Ext";
|
|
2072
|
+
readonly description: "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.";
|
|
2073
|
+
readonly type: "object";
|
|
2074
|
+
readonly minProperties: 1;
|
|
2075
|
+
readonly additionalProperties: true;
|
|
2076
|
+
readonly propertyNames: {
|
|
2077
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
2078
|
+
};
|
|
2079
|
+
};
|
|
2080
|
+
readonly DirectoryDisclosure: {
|
|
2081
|
+
readonly title: "DirectoryDisclosure";
|
|
2082
|
+
readonly description: "The statement itself. Every member is generated from the community's configuration when the statement is read. `statementDigest` names this exact statement, so an applicant can record which one it was shown.";
|
|
2083
|
+
readonly type: "object";
|
|
2084
|
+
readonly additionalProperties: false;
|
|
2085
|
+
readonly required: readonly ["fields", "newCard", "membershipIdentifiers", "adminNotes", "externalCards", "statementDigest"];
|
|
2086
|
+
readonly properties: {
|
|
2087
|
+
readonly fields: {
|
|
2088
|
+
readonly type: "array";
|
|
2089
|
+
readonly maxItems: 128;
|
|
2090
|
+
readonly items: {
|
|
2091
|
+
readonly $ref: "#/$defs/DisclosedField";
|
|
2092
|
+
};
|
|
2093
|
+
readonly description: "Every active field, base and community-defined, in display order. A base field the community has disabled is absent, which is how a reader learns it is not collected.";
|
|
2094
|
+
};
|
|
2095
|
+
readonly newCard: {
|
|
2096
|
+
readonly $ref: "#/$defs/NewCardDefaults";
|
|
2097
|
+
};
|
|
2098
|
+
readonly membershipIdentifiers: {
|
|
2099
|
+
readonly $ref: "#/$defs/Audience";
|
|
2100
|
+
readonly description: "The widest audience a member's membership identifier — the DID they joined with — can reach through the directory: the ceiling of the base field `did`, or `admins` where that field is disabled. `members` or `public` means a member may choose to show it that widely; a new card never shows it beyond `admins` (VTI-DIR-042). Administrators always see it.";
|
|
2101
|
+
};
|
|
2102
|
+
readonly adminNotes: {
|
|
2103
|
+
readonly type: "boolean";
|
|
2104
|
+
readonly description: "Whether administrators keep notes about members. Notes are never on a card and never reach another member; a member may ask for the notes about them.";
|
|
2105
|
+
};
|
|
2106
|
+
readonly groups: {
|
|
2107
|
+
readonly $ref: "#/$defs/GroupDisclosure";
|
|
2108
|
+
};
|
|
2109
|
+
readonly externalCards: {
|
|
2110
|
+
readonly type: "boolean";
|
|
2111
|
+
readonly description: "Whether a member may publish a card beyond the community: their `public` values, signed by them, offered through the community's trust registry. Always the member's own choice, and off on a new card. False where the community cannot publish external cards.";
|
|
2112
|
+
};
|
|
2113
|
+
readonly statementDigest: {
|
|
2114
|
+
readonly $ref: "#/$defs/DigestMultibase";
|
|
2115
|
+
readonly description: "Digest over the RFC 8785 (JCS) canonicalization of this statement with the `statementDigest` member removed, as a multibase-encoded multihash (SHA-256 and base58btc RECOMMENDED). Changes exactly when what the statement says changes.";
|
|
2116
|
+
};
|
|
2117
|
+
readonly ext: {
|
|
2118
|
+
readonly $ref: "#/$defs/Ext";
|
|
2119
|
+
};
|
|
2120
|
+
};
|
|
2121
|
+
};
|
|
2122
|
+
readonly GroupDisclosure: {
|
|
2123
|
+
readonly title: "GroupDisclosure";
|
|
2124
|
+
readonly description: "Present when the community has groups. A member of a group holds a credential, issued by the group's own identifier, that evidences their membership, and can present it outside the community — which is why an applicant is told.";
|
|
2125
|
+
readonly type: "object";
|
|
2126
|
+
readonly additionalProperties: false;
|
|
2127
|
+
readonly required: readonly ["credentialValidity"];
|
|
2128
|
+
readonly properties: {
|
|
2129
|
+
readonly credentialValidity: {
|
|
2130
|
+
readonly type: "string";
|
|
2131
|
+
readonly maxLength: 32;
|
|
2132
|
+
readonly pattern: "^P(([0-9]+W)?([0-9]+D)?T([0-9]+H([0-9]+M)?([0-9]+S)?|[0-9]+M([0-9]+S)?|[0-9]+S)|[0-9]+W([0-9]+D)?|[0-9]+D)$";
|
|
2133
|
+
readonly description: "How long each group membership credential is valid for, as an ISO 8601 duration in weeks, days, hours, minutes and seconds (`P30D`). It is renewed while the member stays in the group, and a credential already issued stays valid until it expires even after its holder leaves.";
|
|
2134
|
+
};
|
|
2135
|
+
};
|
|
2136
|
+
};
|
|
2137
|
+
readonly NewCardDefaults: {
|
|
2138
|
+
readonly title: "NewCardDefaults";
|
|
2139
|
+
readonly description: "The discoverability a card has when the community creates it, before its member chooses. A new card is never published beyond the community (VTI-DIR-042), so there is no member for that here: `externalCards` says whether the member may turn it on.";
|
|
2140
|
+
readonly type: "object";
|
|
2141
|
+
readonly additionalProperties: false;
|
|
2142
|
+
readonly required: readonly ["listing", "search"];
|
|
2143
|
+
readonly properties: {
|
|
2144
|
+
readonly listing: {
|
|
2145
|
+
readonly $ref: "#/$defs/Listing";
|
|
2146
|
+
readonly description: "The listing a new card starts with: the community's `defaultListing` (vtc/directory/fields/list). Every member may always choose `hidden`.";
|
|
2147
|
+
};
|
|
2148
|
+
readonly search: {
|
|
2149
|
+
readonly type: "string";
|
|
2150
|
+
readonly enum: readonly ["byName", "exactNickname", "off"];
|
|
2151
|
+
readonly description: "What a member's search may match, as the card's `discoverability.search`.";
|
|
2152
|
+
};
|
|
2153
|
+
readonly introductions: {
|
|
2154
|
+
readonly $ref: "#/$defs/Introductions";
|
|
2155
|
+
readonly description: "From whom a new card accepts introductions. Absent where the community does not deliver introductions.";
|
|
2156
|
+
};
|
|
2157
|
+
};
|
|
2158
|
+
};
|
|
2159
|
+
readonly Introductions: {
|
|
2160
|
+
readonly title: "Introductions";
|
|
2161
|
+
readonly description: "Who may ask the community to introduce them to this member. `anyone`: any active member who can find the entry. `groups`: only members who share a community group with them. `connections`: only members holding an attributed, in-force verified relationship with them. `off`: nobody. A refused introduction is never reported to its sender.";
|
|
2162
|
+
readonly type: "string";
|
|
2163
|
+
readonly enum: readonly ["anyone", "groups", "connections", "off"];
|
|
2164
|
+
};
|
|
2165
|
+
readonly Listing: {
|
|
2166
|
+
readonly title: "Listing";
|
|
2167
|
+
readonly description: "Whether members can find the entry. `listed`: it appears when members browse. `findable`: it does not appear when browsing, but a search that matches it under `search` returns it. `hidden`: no member finds it by browsing or searching; administrators still see it, and members who share a group that shows its members see it in that group's member list.";
|
|
2168
|
+
readonly type: "string";
|
|
2169
|
+
readonly enum: readonly ["listed", "findable", "hidden"];
|
|
2170
|
+
};
|
|
2171
|
+
readonly DisclosedField: {
|
|
2172
|
+
readonly title: "DisclosedField";
|
|
2173
|
+
readonly description: "One active field of the community's directory, as an applicant needs to see it: what it is, who writes its value, the widest audience it may ever reach and the audience a new card gives it. Disabled and retired fields are not listed: no projection shows them.";
|
|
2174
|
+
readonly type: "object";
|
|
2175
|
+
readonly additionalProperties: false;
|
|
2176
|
+
readonly required: readonly ["key", "label", "type", "source", "ceiling", "defaultVisibility", "searchable"];
|
|
2177
|
+
readonly properties: {
|
|
2178
|
+
readonly key: {
|
|
2179
|
+
readonly $ref: "#/$defs/FieldKey";
|
|
2180
|
+
};
|
|
2181
|
+
readonly label: {
|
|
2182
|
+
readonly $ref: "#/$defs/FieldLabel";
|
|
2183
|
+
};
|
|
2184
|
+
readonly description: {
|
|
2185
|
+
readonly $ref: "#/$defs/FieldDescription";
|
|
2186
|
+
};
|
|
2187
|
+
readonly type: {
|
|
2188
|
+
readonly $ref: "#/$defs/FieldType";
|
|
2189
|
+
};
|
|
2190
|
+
readonly source: {
|
|
2191
|
+
readonly $ref: "#/$defs/FieldSource";
|
|
2192
|
+
readonly description: "Who writes the value. `admin` and `credential` matter most to an applicant: an `admin` field holds what the community asserts about the member, which the member reads and cannot change.";
|
|
2193
|
+
};
|
|
2194
|
+
readonly ceiling: {
|
|
2195
|
+
readonly $ref: "#/$defs/Audience";
|
|
2196
|
+
readonly description: "The widest audience the field may ever reach, whatever the member chooses.";
|
|
2197
|
+
};
|
|
2198
|
+
readonly defaultVisibility: {
|
|
2199
|
+
readonly $ref: "#/$defs/Audience";
|
|
2200
|
+
readonly description: "The audience a new card gives the field until its member chooses. Never wider than `ceiling`.";
|
|
2201
|
+
};
|
|
2202
|
+
readonly searchable: {
|
|
2203
|
+
readonly type: "boolean";
|
|
2204
|
+
readonly description: "Whether a member's search may match the field, within what the searcher may see.";
|
|
2205
|
+
};
|
|
2206
|
+
readonly facet: {
|
|
2207
|
+
readonly type: "boolean";
|
|
2208
|
+
readonly description: "Whether members may filter on the field and see counts by its values. Absent: false.";
|
|
2209
|
+
};
|
|
2210
|
+
};
|
|
2211
|
+
};
|
|
2212
|
+
readonly Audience: {
|
|
2213
|
+
readonly title: "Audience";
|
|
2214
|
+
readonly description: "Who may see a directory field, ordered from narrowest to widest. `admins`: holders of `vtc.directory.admin` (and, for derived fields, `vtc.members.manage`). `groups`: members who share at least one community group with the subject (narrowed to the groups the subject names in `groupAudience`, where it names any). `connections`: members holding an attributed, in-force verified relationship with the subject at the community. `members`: every active member. `public`: anyone, and what the member's signed public card carries outside the community.\n\n`groups` and `connections` are not a chain: a viewer sees a field when they satisfy the audience the subject chose for it or any wider audience. Every audience includes the administrators, and the subject always sees their own whole card. There is no `onlyMe`: a value nobody else should see is not directory data.";
|
|
2215
|
+
readonly type: "string";
|
|
2216
|
+
readonly enum: readonly ["admins", "groups", "connections", "members", "public"];
|
|
2217
|
+
};
|
|
2218
|
+
readonly FieldSource: {
|
|
2219
|
+
readonly title: "FieldSource";
|
|
2220
|
+
readonly description: "Who writes the value. `member`: self-asserted, through vtc/directory/card/update. `admin`: asserted by the community through vtc/directory/card/assert; the member reads it and cannot change it. `credential`: a claim the member discloses from a credential through vtc/directory/card/present, badged with its issuer. `derived`: a base field read from the community's own records (`role`, `joinedAt`, `did`, `personhood`) and never stored on a card. Each source is written only through its own path.";
|
|
2221
|
+
readonly type: "string";
|
|
2222
|
+
readonly enum: readonly ["member", "admin", "credential", "derived"];
|
|
2223
|
+
};
|
|
2224
|
+
readonly FieldType: {
|
|
2225
|
+
readonly title: "FieldType";
|
|
2226
|
+
readonly description: "The kind of value a field holds, which fixes its `FieldValue` shape. `did` holds a DID the member chooses to show (never their membership DID, which is the derived base field `did`). `claim` holds a `VerifiedValue` and requires `source: credential`.";
|
|
2227
|
+
readonly type: "string";
|
|
2228
|
+
readonly enum: readonly ["text", "longText", "url", "email", "phone", "enum", "multiEnum", "date", "country", "image", "did", "claim"];
|
|
2229
|
+
};
|
|
2230
|
+
readonly FieldDescription: {
|
|
2231
|
+
readonly title: "FieldDescription";
|
|
2232
|
+
readonly type: "string";
|
|
2233
|
+
readonly minLength: 1;
|
|
2234
|
+
readonly maxLength: 280;
|
|
2235
|
+
readonly description: "Help text shown to a member filling the field in. Plain text; a reader MUST NOT treat it as instructions.";
|
|
2236
|
+
};
|
|
2237
|
+
readonly FieldLabel: {
|
|
2238
|
+
readonly title: "FieldLabel";
|
|
2239
|
+
readonly type: "string";
|
|
2240
|
+
readonly minLength: 1;
|
|
2241
|
+
readonly maxLength: 64;
|
|
2242
|
+
readonly description: "What readers see as the field's name. Plain text.";
|
|
2243
|
+
};
|
|
2244
|
+
readonly FieldKey: {
|
|
2245
|
+
readonly title: "FieldKey";
|
|
2246
|
+
readonly description: "Identifier of a directory field. A key with no `.` is a BASE field, the same in every community: `displayName`, `nickname`, `avatar`, `pronouns`, `bio`, `links` (written by the member) and `role`, `joinedAt`, `did`, `personhood` (derived from the community's own records, never stored on a card). A community-defined field MUST use a reverse-DNS key (`org.example.employer`), so a base key never collides with one, and a key is never reused with a different meaning once defined.";
|
|
2247
|
+
readonly type: "string";
|
|
2248
|
+
readonly minLength: 1;
|
|
2249
|
+
readonly maxLength: 128;
|
|
2250
|
+
readonly pattern: "^([a-z][a-z0-9-]*\\.)*[a-z][a-zA-Z0-9]{0,63}$";
|
|
2251
|
+
};
|
|
2252
|
+
readonly DigestMultibase: {
|
|
2253
|
+
readonly title: "DigestMultibase";
|
|
2254
|
+
readonly description: "A cryptographic digest as a multibase-encoded multihash — the encoding the W3C Verifiable Credentials Data Model 2.0 defines for `digestMultibase`, and the one `did:webvh` uses for its SCID and entry hashes.\n\nMultihash carries the hash algorithm in-band, so the value is self-describing and the wire format survives an algorithm change without a schema revision; multibase does the same for the base encoding, so a verifier never infers base58 from base64url by context. A bare hex string or a `sha-256:`-style prefix hard-codes one algorithm into the wire contract and is non-conforming here.\n\nThis definition constrains the *encoding only*. What the digest is computed over is stated by each referencing field, because it differs legitimately: a digest over a JSON document is taken over its RFC 8785 (JCS) canonicalization, while a digest over an opaque artifact is taken over its bytes. A field whose input is a JSON document and which does not name a canonicalization is not reproducible.\n\nRestricted to the two multibase headers W3C Controlled Identifiers 1.0 §2.4 normatively requires — `z` (base58btc) and `u` (base64url-no-pad). CID permits others but states that \"interoperability is not guaranteed between implementations using such values\", and a registry whose purpose is interoperability should not mint digests a conforming verifier may be unable to read. The alphabets are enforced rather than assumed: base58btc excludes 0, O, I and l, and an earlier permissive pattern let three published examples carry digests that were not valid base58 at all. base58btc is RECOMMENDED, for consistency with `did:key` and `did:webvh`.";
|
|
2255
|
+
readonly type: "string";
|
|
2256
|
+
readonly minLength: 16;
|
|
2257
|
+
readonly pattern: "^(z[1-9A-HJ-NP-Za-km-z]+|u[A-Za-z0-9_-]+)$";
|
|
2258
|
+
readonly examples: readonly ["zQmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"];
|
|
2259
|
+
};
|
|
2260
|
+
readonly ExtCritical: {
|
|
2261
|
+
readonly title: "ExtCritical";
|
|
2262
|
+
readonly description: "Names the `ext` namespaces a consumer MUST understand or refuse, per SPEC.md §4.5.1.\n\nEvery entry MUST be an immediate key of the sibling `ext` object at the same level; an entry naming an absent namespace is non-conforming and the consumer rejects the document with `malformedRequest`. A consumer that does not recognize a namespace named here MUST NOT process the document as though the namespace were absent, and rejects it with `unsupportedExtension` — the exception to the rule that unrecognized namespaces are ignored.\n\nA producer marks a namespace only where the document's meaning depends on it. Marking one that merely carries a hint or an annotation turns every consumer that has not implemented it into a failure where it would otherwise have interoperated. JSON Schema cannot check either of those rules: that an entry names a present namespace is checkable only against the sibling `ext`, and whether a namespace is load-bearing is not a schema question at all. Both are consumer-side checks.";
|
|
2263
|
+
readonly type: "array";
|
|
2264
|
+
readonly minItems: 1;
|
|
2265
|
+
readonly uniqueItems: true;
|
|
2266
|
+
readonly items: {
|
|
2267
|
+
readonly type: "string";
|
|
2268
|
+
readonly pattern: "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$";
|
|
2269
|
+
};
|
|
2270
|
+
readonly examples: readonly [readonly ["org.openvtc.hidden-vetting"]];
|
|
2271
|
+
};
|
|
2272
|
+
readonly VettingRelationship: {
|
|
2273
|
+
readonly title: "VettingRelationship";
|
|
2274
|
+
readonly type: "string";
|
|
2275
|
+
readonly enum: readonly ["none", "communityColleague", "sameEmployer", "family", "otherPersonal"];
|
|
2276
|
+
readonly description: "The vetter's own declaration of how they relate to the applicant. Declared, not verified: it exists so community policy can cap how much evidence comes from people close to the applicant, and a false declaration is the vetter's attributable act.";
|
|
2277
|
+
};
|
|
2278
|
+
readonly ClaimType: {
|
|
2279
|
+
readonly title: "ClaimType";
|
|
2280
|
+
readonly description: "The vocabulary token naming what a value IS — `name.legal`, `phone.mobile`, `address.postal`, `person.birthDate`. Dotted, most-general segment first, so that a consumer with no knowledge of the specific token can still group by its prefix.\n\nThe token is the maintainer's own; no external vocabulary is primary. External vocabularies (vCard/jCard, OIDC standard claims, schema.org) are mappings applied at PRESENTATION by a renderer, not at rest, so that a query written in any of them can be matched without the store having to live inside any one of them.\n\nThe `x:` prefix is an open extension namespace and is not decoration. The closest prior art — Windows CardSpace's self-issued card — supported exactly fifteen predefined claim types with no extensibility, and that is the specific way it failed the requirement a holder actually has. An `x:` attribute stores, composes, binds and discloses exactly like a known one; it renders generically and matches only an explicit query.";
|
|
2281
|
+
readonly type: "string";
|
|
2282
|
+
readonly minLength: 1;
|
|
2283
|
+
readonly maxLength: 128;
|
|
2284
|
+
readonly pattern: "^(x:)?[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$";
|
|
2285
|
+
};
|
|
2286
|
+
readonly VettingDocumentation: {
|
|
2287
|
+
readonly title: "VettingDocumentation";
|
|
2288
|
+
readonly type: "string";
|
|
2289
|
+
readonly minLength: 1;
|
|
2290
|
+
readonly maxLength: 64;
|
|
2291
|
+
readonly pattern: "^[a-z][a-zA-Z0-9]*$";
|
|
2292
|
+
readonly description: "A class of documentation, named in lowerCamelCase. Open rather than enumerated, because what documentation a vetter accepts is each vetter's own choice. Well-known values: `passport`, `nationalId`, `driverLicence`, and `none` — the vetter will attest without a document, which is the `priorAcquaintance` case. Only the class ever travels — never a document number, an image, an issuing authority or an expiry date. `none` states a policy (what a vetter accepts); a record of what was relied on expresses 'no document' as an empty list instead.";
|
|
2293
|
+
};
|
|
2294
|
+
readonly VettingMethod: {
|
|
2295
|
+
readonly title: "VettingMethod";
|
|
2296
|
+
readonly type: "string";
|
|
2297
|
+
readonly enum: readonly ["inPerson", "video", "priorAcquaintance"];
|
|
2298
|
+
readonly description: "How the vetter established that the person they checked is the person controlling the applicant's DID. `inPerson` — both people were physically together. `video` — a live, two-way video call. `priorAcquaintance` — the vetter has known or worked with this person over a period, and attests from that knowledge rather than from a document. A method is a description of what happened, not an assurance level: which methods count, and how many of each, is community policy.";
|
|
2299
|
+
};
|
|
2300
|
+
};
|
|
2301
|
+
};
|
|
2302
|
+
};
|
|
2303
|
+
//# sourceMappingURL=payload.d.ts.map
|