@mdbase-dev/connect-protocol 0.1.0-beta.113 → 0.1.0-beta.114
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/dist/index.d.ts +6 -6
- package/dist/index.js +1 -0
- package/dist/manifest.js +18 -0
- package/dist/people.d.ts +33 -0
- package/dist/people.js +26 -0
- package/dist/type-packs.d.ts +5 -0
- package/package.json +1 -1
- package/schemas/mdbase-app.schema.json +24 -0
package/dist/index.d.ts
CHANGED
|
@@ -177,10 +177,13 @@ export interface ApplicationRequirements {
|
|
|
177
177
|
access?: "contract" | "full_collection";
|
|
178
178
|
/** Restrict authorization to durable provider-backed collections. */
|
|
179
179
|
collection_kind?: "hosted";
|
|
180
|
+
/** Explicit identity consent. Omission discloses no account metadata. */
|
|
181
|
+
people?: import("./people.js").ApplicationPeopleRequirement;
|
|
180
182
|
/** First-class non-Markdown file access requested independently of records. */
|
|
181
183
|
files?: ApplicationFileRequirement;
|
|
182
184
|
}
|
|
183
|
-
export type
|
|
185
|
+
export { PEOPLE_PERMISSIONS, approvedPeoplePermissions, type AccountIdentity, type AccountProfile, type CurrentAccountResponse, type CollectionMemberProfile, type ApplicationPeopleRequirement, type PeoplePermission } from "./people.js";
|
|
186
|
+
export type LegacyApplicationRequirements = Omit<ApplicationRequirements, "capabilities" | "files" | "access" | "people"> & {
|
|
184
187
|
access: "full_collection";
|
|
185
188
|
capabilities?: LegacyApplicationCapabilityRequirements;
|
|
186
189
|
files?: LegacyApplicationFileRequirement;
|
|
@@ -198,11 +201,7 @@ export interface ApplicationProvisions {
|
|
|
198
201
|
configuration?: ConfigurationProvision[];
|
|
199
202
|
}
|
|
200
203
|
export interface GrantScope {
|
|
201
|
-
/**
|
|
202
|
-
* Legacy semantic scope payload retained for wire/storage compatibility.
|
|
203
|
-
* Canonical application grants use an empty array; contracts remain available
|
|
204
|
-
* through collection resources and operation-level semantic selectors.
|
|
205
|
-
*/
|
|
204
|
+
/** Legacy scope only; canonical grants use an empty array and discover contracts through resources and semantic selectors. */
|
|
206
205
|
contracts: CollectionContractDescriptor[];
|
|
207
206
|
/** New authority must be `full_collection`; `contract` is legacy-only. */
|
|
208
207
|
access: "contract" | "full_collection";
|
|
@@ -784,6 +783,7 @@ export interface QueryRecord<Frontmatter extends JsonObject = JsonObject> {
|
|
|
784
783
|
file: Partial<CollectionFileMetadata> & {
|
|
785
784
|
path?: string;
|
|
786
785
|
};
|
|
786
|
+
values?: JsonObject;
|
|
787
787
|
/** Present when the authority returned a normalized contract projection. */
|
|
788
788
|
contract?: DataContractViewIdentity;
|
|
789
789
|
}
|
package/dist/index.js
CHANGED
package/dist/manifest.js
CHANGED
|
@@ -282,6 +282,17 @@ function validateProvisionRequirements(value) {
|
|
|
282
282
|
}
|
|
283
283
|
for (const [resourceIndex, resource] of declaredResources.entries()) {
|
|
284
284
|
const source = String(resource.source);
|
|
285
|
+
if (resource.upgrade_from !== undefined) {
|
|
286
|
+
const baseline = asObject(resource.upgrade_from);
|
|
287
|
+
const path = `/provisions/type_packs/${packIndex}/manifest/resources/${resourceIndex}/upgrade_from`;
|
|
288
|
+
if (resource.kind !== "type" || resource.mode !== "seed") {
|
|
289
|
+
issues.push(issue(path, "seedUpgrade", "is only allowed for seed types"));
|
|
290
|
+
}
|
|
291
|
+
if (typeof baseline.document === "string"
|
|
292
|
+
&& baseline.digest !== `sha256:${createHash("sha256").update(baseline.document).digest("hex")}`) {
|
|
293
|
+
issues.push(issue(`${path}/digest`, "digest", "does not match the baseline document"));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
285
296
|
const document = embedded.get(source);
|
|
286
297
|
if (typeof document !== "string") {
|
|
287
298
|
issues.push(issue(`/provisions/type_packs/${packIndex}/resources`, "resourceSet", `is missing manifest source ${source}`));
|
|
@@ -409,6 +420,13 @@ function validateCapabilityRequirements(value) {
|
|
|
409
420
|
if (fileOverlap) {
|
|
410
421
|
issues.push(issue("/requirements/files/optional", "disjoint", `must not repeat required file action ${fileOverlap}`));
|
|
411
422
|
}
|
|
423
|
+
const people = asObject(requirements.people);
|
|
424
|
+
const requiredPeople = Array.isArray(people.required) ? people.required.map(String) : [];
|
|
425
|
+
const optionalPeople = Array.isArray(people.optional) ? people.optional.map(String) : [];
|
|
426
|
+
const peopleOverlap = optionalPeople.find((permission) => requiredPeople.includes(permission));
|
|
427
|
+
if (peopleOverlap) {
|
|
428
|
+
issues.push(issue("/requirements/people/optional", "disjoint", `must not repeat required people permission ${peopleOverlap}`));
|
|
429
|
+
}
|
|
412
430
|
return issues;
|
|
413
431
|
}
|
|
414
432
|
// Frozen cross-field rules from c2596a6e; notably, absent capabilities skip
|
package/dist/people.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const PEOPLE_PERMISSIONS: readonly ["identity", "members"];
|
|
2
|
+
export type PeoplePermission = (typeof PEOPLE_PERMISSIONS)[number];
|
|
3
|
+
/**
|
|
4
|
+
* Control-plane consent declared in the exact application manifest. Required
|
|
5
|
+
* permissions gate approval; the approving user chooses optional ones, and the
|
|
6
|
+
* grant records the result.
|
|
7
|
+
*/
|
|
8
|
+
export interface ApplicationPeopleRequirement {
|
|
9
|
+
version: 1;
|
|
10
|
+
required?: PeoplePermission[];
|
|
11
|
+
optional?: PeoplePermission[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Validates an approval choice against a declaration. An omitted choice
|
|
15
|
+
* approves every declared permission, matching file-action approval.
|
|
16
|
+
*/
|
|
17
|
+
export declare function approvedPeoplePermissions(requirement: ApplicationPeopleRequirement | undefined, selected?: readonly string[]): PeoplePermission[];
|
|
18
|
+
/** Portable account identity, not a credential or collection permission. */
|
|
19
|
+
export interface AccountIdentity {
|
|
20
|
+
issuer: string;
|
|
21
|
+
subject: string;
|
|
22
|
+
}
|
|
23
|
+
export interface AccountProfile extends AccountIdentity {
|
|
24
|
+
name: string;
|
|
25
|
+
}
|
|
26
|
+
/** Wire response for the current account. */
|
|
27
|
+
export interface CurrentAccountResponse extends AccountProfile {
|
|
28
|
+
/** Where this account manages its person record; a route, never an identity. */
|
|
29
|
+
person_settings_url?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface CollectionMemberProfile extends AccountProfile {
|
|
32
|
+
role: "owner" | "editor" | "viewer";
|
|
33
|
+
}
|
package/dist/people.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const PEOPLE_PERMISSIONS = ["identity", "members"];
|
|
2
|
+
/**
|
|
3
|
+
* Validates an approval choice against a declaration. An omitted choice
|
|
4
|
+
* approves every declared permission, matching file-action approval.
|
|
5
|
+
*/
|
|
6
|
+
export function approvedPeoplePermissions(requirement, selected) {
|
|
7
|
+
if (!requirement) {
|
|
8
|
+
if (selected?.length)
|
|
9
|
+
throw new Error("People permissions require an application people declaration.");
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const required = requirement.required ?? [];
|
|
13
|
+
const optional = requirement.optional ?? [];
|
|
14
|
+
const declared = new Set([...required, ...optional]);
|
|
15
|
+
if (requirement.version !== 1
|
|
16
|
+
|| declared.size === 0
|
|
17
|
+
|| declared.size !== required.length + optional.length
|
|
18
|
+
|| [...declared].some((permission) => !PEOPLE_PERMISSIONS.includes(permission))) {
|
|
19
|
+
throw new Error("People requirements need unique, disjoint, known required and optional permissions.");
|
|
20
|
+
}
|
|
21
|
+
const chosen = new Set(selected ?? declared);
|
|
22
|
+
if (required.some((permission) => !chosen.has(permission)) || [...chosen].some((permission) => !declared.has(permission))) {
|
|
23
|
+
throw new Error("Required people permissions must be approved and optional people permissions must be declared.");
|
|
24
|
+
}
|
|
25
|
+
return PEOPLE_PERMISSIONS.filter((permission) => chosen.has(permission));
|
|
26
|
+
}
|
package/dist/type-packs.d.ts
CHANGED
|
@@ -36,6 +36,11 @@ export declare const MDBASE_TIMER_FIRED_CONTRACT: {
|
|
|
36
36
|
readonly digest: "sha256:41105be7a7abf33b31ced47e1e1965242236e40ccaea286b959b0a8c591f5642";
|
|
37
37
|
};
|
|
38
38
|
export interface TypePackManifestResource {
|
|
39
|
+
/** Explicit three-way upgrade; only valid for seed type resources. */
|
|
40
|
+
upgrade_from?: {
|
|
41
|
+
digest: string;
|
|
42
|
+
document: string;
|
|
43
|
+
};
|
|
39
44
|
kind: "contract" | "type" | "schema";
|
|
40
45
|
mode: "managed" | "seed";
|
|
41
46
|
source: string;
|
package/package.json
CHANGED
|
@@ -122,6 +122,17 @@
|
|
|
122
122
|
"const": "hosted",
|
|
123
123
|
"description": "Require a durable provider-backed collection with direct sync support."
|
|
124
124
|
},
|
|
125
|
+
"people": {
|
|
126
|
+
"type": "object",
|
|
127
|
+
"additionalProperties": false,
|
|
128
|
+
"required": ["version"],
|
|
129
|
+
"anyOf": [{ "required": ["required"] }, { "required": ["optional"] }],
|
|
130
|
+
"properties": {
|
|
131
|
+
"version": { "const": 1 },
|
|
132
|
+
"required": { "$ref": "#/$defs/peoplePermissions" },
|
|
133
|
+
"optional": { "$ref": "#/$defs/peoplePermissions" }
|
|
134
|
+
}
|
|
135
|
+
},
|
|
125
136
|
"files": { "$ref": "#/$defs/fileRequirement" },
|
|
126
137
|
"configuration": {
|
|
127
138
|
"type": "array",
|
|
@@ -208,6 +219,10 @@
|
|
|
208
219
|
"offline.replica"
|
|
209
220
|
]
|
|
210
221
|
},
|
|
222
|
+
"peoplePermissions": {
|
|
223
|
+
"type": "array", "minItems": 1, "uniqueItems": true,
|
|
224
|
+
"items": { "enum": ["identity", "members"] }
|
|
225
|
+
},
|
|
211
226
|
"fileRequirement": {
|
|
212
227
|
"type": "object",
|
|
213
228
|
"additionalProperties": false,
|
|
@@ -303,6 +318,15 @@
|
|
|
303
318
|
"properties": {
|
|
304
319
|
"kind": { "enum": ["contract", "type", "schema"] },
|
|
305
320
|
"mode": { "enum": ["managed", "seed"] },
|
|
321
|
+
"upgrade_from": {
|
|
322
|
+
"type": "object",
|
|
323
|
+
"additionalProperties": false,
|
|
324
|
+
"required": ["digest", "document"],
|
|
325
|
+
"properties": {
|
|
326
|
+
"digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
|
|
327
|
+
"document": { "type": "string", "maxLength": 262144 }
|
|
328
|
+
}
|
|
329
|
+
},
|
|
306
330
|
"source": { "type": "string", "minLength": 1, "maxLength": 240 },
|
|
307
331
|
"target": { "type": "string", "minLength": 1, "maxLength": 240 },
|
|
308
332
|
"digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }
|