@haverstack/core 0.41.0 → 0.43.0
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/README.md +124 -64
- package/dist/access.d.ts +43 -47
- package/dist/access.d.ts.map +1 -1
- package/dist/access.js +66 -101
- package/dist/access.js.map +1 -1
- package/dist/{combine.d.ts → adapter/combine.d.ts} +8 -1
- package/dist/adapter/combine.d.ts.map +1 -0
- package/dist/{combine.js → adapter/combine.js} +18 -3
- package/dist/adapter/combine.js.map +1 -0
- package/dist/adapter/index.d.ts +19 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +16 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/adapter/reach.d.ts +14 -0
- package/dist/adapter/reach.d.ts.map +1 -0
- package/dist/adapter/reach.js +31 -0
- package/dist/adapter/reach.js.map +1 -0
- package/dist/{sort.d.ts → adapter/sort.d.ts} +20 -20
- package/dist/adapter/sort.d.ts.map +1 -0
- package/dist/{sort.js → adapter/sort.js} +37 -27
- package/dist/adapter/sort.js.map +1 -0
- package/dist/associations/identity.d.ts +69 -0
- package/dist/associations/identity.d.ts.map +1 -0
- package/dist/associations/identity.js +174 -0
- package/dist/associations/identity.js.map +1 -0
- package/dist/associations/validation.d.ts +83 -0
- package/dist/associations/validation.d.ts.map +1 -0
- package/dist/associations/validation.js +312 -0
- package/dist/associations/validation.js.map +1 -0
- package/dist/attachment-records.d.ts +48 -0
- package/dist/attachment-records.d.ts.map +1 -0
- package/dist/attachment-records.js +52 -0
- package/dist/attachment-records.js.map +1 -0
- package/dist/collection.d.ts +178 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +397 -0
- package/dist/collection.js.map +1 -0
- package/dist/content-match.d.ts +25 -0
- package/dist/content-match.d.ts.map +1 -0
- package/dist/content-match.js +51 -0
- package/dist/content-match.js.map +1 -0
- package/dist/content-translation.d.ts +42 -0
- package/dist/content-translation.d.ts.map +1 -0
- package/dist/content-translation.js +108 -0
- package/dist/content-translation.js.map +1 -0
- package/dist/did/did.d.ts.map +1 -0
- package/dist/{did.js → did/did.js} +3 -4
- package/dist/did/did.js.map +1 -0
- package/dist/{did-entry.d.ts → did/index.d.ts} +1 -1
- package/dist/did/index.d.ts.map +1 -0
- package/dist/{did-entry.js → did/index.js} +3 -3
- package/dist/did/index.js.map +1 -0
- package/dist/errors.d.ts +54 -66
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +58 -62
- package/dist/errors.js.map +1 -1
- package/dist/grants.d.ts +20 -44
- package/dist/grants.d.ts.map +1 -1
- package/dist/grants.js +69 -151
- package/dist/grants.js.map +1 -1
- package/dist/id.d.ts +13 -31
- package/dist/id.d.ts.map +1 -1
- package/dist/id.js +13 -31
- package/dist/id.js.map +1 -1
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +3 -6
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +6 -10
- package/dist/install.js.map +1 -1
- package/dist/lazy.d.ts +13 -0
- package/dist/lazy.d.ts.map +1 -0
- package/dist/lazy.js +27 -0
- package/dist/lazy.js.map +1 -0
- package/dist/merge.d.ts +1 -1
- package/dist/merge.d.ts.map +1 -1
- package/dist/merge.js +6 -12
- package/dist/merge.js.map +1 -1
- package/dist/migration-steps.d.ts +102 -0
- package/dist/migration-steps.d.ts.map +1 -0
- package/dist/migration-steps.js +293 -0
- package/dist/migration-steps.js.map +1 -0
- package/dist/query-validation.d.ts +68 -121
- package/dist/query-validation.d.ts.map +1 -1
- package/dist/query-validation.js +214 -380
- package/dist/query-validation.js.map +1 -1
- package/dist/record-changes.d.ts +11 -150
- package/dist/record-changes.d.ts.map +1 -1
- package/dist/record-changes.js +14 -305
- package/dist/record-changes.js.map +1 -1
- package/dist/schema.d.ts +18 -7
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +59 -30
- package/dist/schema.js.map +1 -1
- package/dist/scoped-stack/authority-snapshot.d.ts +37 -0
- package/dist/scoped-stack/authority-snapshot.d.ts.map +1 -0
- package/dist/scoped-stack/authority-snapshot.js +49 -0
- package/dist/scoped-stack/authority-snapshot.js.map +1 -0
- package/dist/scoped-stack/authority.d.ts +169 -0
- package/dist/scoped-stack/authority.d.ts.map +1 -0
- package/dist/scoped-stack/authority.js +408 -0
- package/dist/scoped-stack/authority.js.map +1 -0
- package/dist/scoped-stack/family-policy.d.ts +59 -0
- package/dist/scoped-stack/family-policy.d.ts.map +1 -0
- package/dist/scoped-stack/family-policy.js +68 -0
- package/dist/scoped-stack/family-policy.js.map +1 -0
- package/dist/scoped-stack/scoped-stack.d.ts +318 -0
- package/dist/scoped-stack/scoped-stack.d.ts.map +1 -0
- package/dist/scoped-stack/scoped-stack.js +695 -0
- package/dist/scoped-stack/scoped-stack.js.map +1 -0
- package/dist/scoped-stack/subscription.d.ts +36 -0
- package/dist/scoped-stack/subscription.d.ts.map +1 -0
- package/dist/scoped-stack/subscription.js +69 -0
- package/dist/scoped-stack/subscription.js.map +1 -0
- package/dist/stack/arguments.d.ts +27 -0
- package/dist/stack/arguments.d.ts.map +1 -0
- package/dist/stack/arguments.js +53 -0
- package/dist/stack/arguments.js.map +1 -0
- package/dist/stack/attachments.d.ts +24 -0
- package/dist/stack/attachments.d.ts.map +1 -0
- package/dist/stack/attachments.js +113 -0
- package/dist/stack/attachments.js.map +1 -0
- package/dist/{changes.d.ts → stack/changes.d.ts} +30 -72
- package/dist/stack/changes.d.ts.map +1 -0
- package/dist/{changes.js → stack/changes.js} +40 -74
- package/dist/stack/changes.js.map +1 -0
- package/dist/stack/client.d.ts +247 -0
- package/dist/stack/client.d.ts.map +1 -0
- package/dist/stack/client.js +9 -0
- package/dist/stack/client.js.map +1 -0
- package/dist/stack/identity-bindings.d.ts.map +1 -0
- package/dist/{identity-bindings.js → stack/identity-bindings.js} +5 -14
- package/dist/stack/identity-bindings.js.map +1 -0
- package/dist/stack/install-app.d.ts +22 -0
- package/dist/stack/install-app.d.ts.map +1 -0
- package/dist/stack/install-app.js +262 -0
- package/dist/stack/install-app.js.map +1 -0
- package/dist/stack/integrity.d.ts +94 -0
- package/dist/stack/integrity.d.ts.map +1 -0
- package/dist/stack/integrity.js +268 -0
- package/dist/stack/integrity.js.map +1 -0
- package/dist/{limits.d.ts → stack/limits.d.ts} +2 -5
- package/dist/stack/limits.d.ts.map +1 -0
- package/dist/{limits.js → stack/limits.js} +3 -6
- package/dist/stack/limits.js.map +1 -0
- package/dist/stack/migrations.d.ts +59 -0
- package/dist/stack/migrations.d.ts.map +1 -0
- package/dist/stack/migrations.js +141 -0
- package/dist/stack/migrations.js.map +1 -0
- package/dist/stack/reads.d.ts +69 -0
- package/dist/stack/reads.d.ts.map +1 -0
- package/dist/stack/reads.js +141 -0
- package/dist/stack/reads.js.map +1 -0
- package/dist/stack/record-id.d.ts +35 -0
- package/dist/stack/record-id.d.ts.map +1 -0
- package/dist/stack/record-id.js +82 -0
- package/dist/stack/record-id.js.map +1 -0
- package/dist/stack/stack.d.ts +444 -0
- package/dist/stack/stack.d.ts.map +1 -0
- package/dist/stack/stack.js +1339 -0
- package/dist/stack/stack.js.map +1 -0
- package/dist/stack/system-types.d.ts +16 -0
- package/dist/stack/system-types.d.ts.map +1 -0
- package/dist/stack/system-types.js +111 -0
- package/dist/stack/system-types.js.map +1 -0
- package/dist/stack/type-grants.d.ts +20 -0
- package/dist/stack/type-grants.d.ts.map +1 -0
- package/dist/stack/type-grants.js +69 -0
- package/dist/stack/type-grants.js.map +1 -0
- package/dist/stack/write-expectation.d.ts +79 -0
- package/dist/stack/write-expectation.d.ts.map +1 -0
- package/dist/stack/write-expectation.js +71 -0
- package/dist/stack/write-expectation.js.map +1 -0
- package/dist/stack/write-gate.d.ts +23 -0
- package/dist/stack/write-gate.d.ts.map +1 -0
- package/dist/stack/write-gate.js +17 -0
- package/dist/stack/write-gate.js.map +1 -0
- package/dist/testing.d.ts +44 -33
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +180 -176
- package/dist/testing.js.map +1 -1
- package/dist/type-handle.d.ts +67 -78
- package/dist/type-handle.d.ts.map +1 -1
- package/dist/type-handle.js +44 -111
- package/dist/type-handle.js.map +1 -1
- package/dist/types/adapter.d.ts +282 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +5 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/associations.d.ts +140 -0
- package/dist/types/associations.d.ts.map +1 -0
- package/dist/types/associations.js +6 -0
- package/dist/types/associations.js.map +1 -0
- package/dist/types/capabilities.d.ts +89 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +5 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/events.d.ts +150 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +5 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/ids.d.ts +43 -0
- package/dist/types/ids.d.ts.map +1 -0
- package/dist/types/ids.js +5 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/index.d.ts +19 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/journal.d.ts +47 -0
- package/dist/types/journal.d.ts.map +1 -0
- package/dist/types/journal.js +5 -0
- package/dist/types/journal.js.map +1 -0
- package/dist/types/query.d.ts +185 -0
- package/dist/types/query.d.ts.map +1 -0
- package/dist/types/query.js +10 -0
- package/dist/types/query.js.map +1 -0
- package/dist/types/records.d.ts +76 -0
- package/dist/types/records.d.ts.map +1 -0
- package/dist/types/records.js +5 -0
- package/dist/types/records.js.map +1 -0
- package/dist/types/schema.d.ts +74 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +5 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/types/system.d.ts +161 -0
- package/dist/types/system.d.ts.map +1 -0
- package/dist/types/system.js +32 -0
- package/dist/types/system.js.map +1 -0
- package/dist/types/tokens.d.ts +39 -0
- package/dist/types/tokens.d.ts.map +1 -0
- package/dist/types/tokens.js +5 -0
- package/dist/types/tokens.js.map +1 -0
- package/dist/validate.d.ts +31 -70
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +52 -92
- package/dist/validate.js.map +1 -1
- package/dist/{attachment-download.d.ts → wire/attachment-download.d.ts} +0 -57
- package/dist/wire/attachment-download.d.ts.map +1 -0
- package/dist/{attachment-download.js → wire/attachment-download.js} +0 -61
- package/dist/wire/attachment-download.js.map +1 -0
- package/dist/{auth.d.ts → wire/auth.d.ts} +5 -8
- package/dist/wire/auth.d.ts.map +1 -0
- package/dist/{auth.js → wire/auth.js} +5 -8
- package/dist/wire/auth.js.map +1 -0
- package/dist/{wire-body.d.ts → wire/body.d.ts} +35 -12
- package/dist/wire/body.d.ts.map +1 -0
- package/dist/{wire-body.js → wire/body.js} +74 -13
- package/dist/wire/body.js.map +1 -0
- package/dist/{wire-entry.d.ts → wire/index.d.ts} +12 -12
- package/dist/wire/index.d.ts.map +1 -0
- package/dist/{wire-entry.js → wire/index.js} +13 -17
- package/dist/wire/index.js.map +1 -0
- package/dist/wire/record.d.ts +31 -0
- package/dist/wire/record.d.ts.map +1 -0
- package/dist/{wire-record.js → wire/record.js} +7 -67
- package/dist/wire/record.js.map +1 -0
- package/dist/{wire-request.d.ts → wire/request.d.ts} +32 -49
- package/dist/wire/request.d.ts.map +1 -0
- package/dist/{wire-request.js → wire/request.js} +113 -83
- package/dist/wire/request.js.map +1 -0
- package/package.json +7 -7
- package/dist/adapter-entry.d.ts +0 -16
- package/dist/adapter-entry.d.ts.map +0 -1
- package/dist/adapter-entry.js +0 -14
- package/dist/adapter-entry.js.map +0 -1
- package/dist/attachment-download.d.ts.map +0 -1
- package/dist/attachment-download.js.map +0 -1
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js.map +0 -1
- package/dist/changes.d.ts.map +0 -1
- package/dist/changes.js.map +0 -1
- package/dist/combine.d.ts.map +0 -1
- package/dist/combine.js.map +0 -1
- package/dist/did-entry.d.ts.map +0 -1
- package/dist/did-entry.js.map +0 -1
- package/dist/did.d.ts.map +0 -1
- package/dist/did.js.map +0 -1
- package/dist/identity-bindings.d.ts.map +0 -1
- package/dist/identity-bindings.js.map +0 -1
- package/dist/limits.d.ts.map +0 -1
- package/dist/limits.js.map +0 -1
- package/dist/record-id.d.ts +0 -70
- package/dist/record-id.d.ts.map +0 -1
- package/dist/record-id.js +0 -127
- package/dist/record-id.js.map +0 -1
- package/dist/scoped-stack.d.ts +0 -549
- package/dist/scoped-stack.d.ts.map +0 -1
- package/dist/scoped-stack.js +0 -1301
- package/dist/scoped-stack.js.map +0 -1
- package/dist/sort.d.ts.map +0 -1
- package/dist/sort.js.map +0 -1
- package/dist/stack-reads.d.ts +0 -38
- package/dist/stack-reads.d.ts.map +0 -1
- package/dist/stack-reads.js +0 -79
- package/dist/stack-reads.js.map +0 -1
- package/dist/stack.d.ts +0 -1032
- package/dist/stack.d.ts.map +0 -1
- package/dist/stack.js +0 -2337
- package/dist/stack.js.map +0 -1
- package/dist/types.d.ts +0 -1278
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -51
- package/dist/types.js.map +0 -1
- package/dist/wire-body.d.ts.map +0 -1
- package/dist/wire-body.js.map +0 -1
- package/dist/wire-entry.d.ts.map +0 -1
- package/dist/wire-entry.js.map +0 -1
- package/dist/wire-record.d.ts +0 -50
- package/dist/wire-record.d.ts.map +0 -1
- package/dist/wire-record.js.map +0 -1
- package/dist/wire-request.d.ts.map +0 -1
- package/dist/wire-request.js.map +0 -1
- /package/dist/{did.d.ts → did/did.d.ts} +0 -0
- /package/dist/{identity-bindings.d.ts → stack/identity-bindings.d.ts} +0 -0
package/dist/schema.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stack — Schema Utilities
|
|
3
3
|
* -------------------------------------------------------
|
|
4
|
-
*
|
|
4
|
+
* What can be said about a TypeSchema and a TypeId without a stack: a
|
|
5
|
+
* schema's hash, whether one schema reads as another, whether one is a
|
|
6
|
+
* legal in-place evolution of another, and how a TypeId splits into its
|
|
7
|
+
* family and version.
|
|
5
8
|
*
|
|
6
9
|
* Hashing produces a stable SHA-256 fingerprint of a TypeSchema
|
|
7
10
|
* by canonicalizing it first (alphabetical keys, minified JSON).
|
|
8
11
|
* This is used for drift detection — not type identity, which is
|
|
9
12
|
* the namespaced ID controlled by the app author.
|
|
10
13
|
*/
|
|
11
|
-
import type { TypeSchema } from './types.js';
|
|
14
|
+
import type { TypeSchema } from './types/index.js';
|
|
12
15
|
import type { ReadonlyTypeSchema } from './type-handle.js';
|
|
13
16
|
/**
|
|
14
17
|
* Compute a stable SHA-256 hash of a TypeSchema.
|
|
@@ -36,6 +39,12 @@ export type SchemaDriftViolation = {
|
|
|
36
39
|
* docs/spec/data-model.md § Schema drift detection.
|
|
37
40
|
*/
|
|
38
41
|
export declare const diffSchemas: (stored: TypeSchema, candidate: TypeSchema) => SchemaDriftViolation[];
|
|
42
|
+
/**
|
|
43
|
+
* A schema's top-level `file-ref` fields — the content half of what a
|
|
44
|
+
* record references, beside its attachment associations. A nested one is
|
|
45
|
+
* validated but is not a reference. See docs/spec/data-model.md § Types.
|
|
46
|
+
*/
|
|
47
|
+
export declare const fileRefFields: (schema: ReadonlyTypeSchema) => string[];
|
|
39
48
|
/**
|
|
40
49
|
* Parse a versioned TypeId into its base and version components.
|
|
41
50
|
* e.g. "com.example.myapp/note@2" → { baseId: "com.example.myapp/note", version: 2 }
|
|
@@ -45,17 +54,19 @@ export declare const parseTypeId: (typeId: string) => {
|
|
|
45
54
|
baseId: string;
|
|
46
55
|
version: number;
|
|
47
56
|
} | null;
|
|
48
|
-
/**
|
|
49
|
-
* Build a versioned TypeId from a base ID and version number.
|
|
50
|
-
* e.g. ("com.example.myapp/note", 2) → "com.example.myapp/note@2"
|
|
51
|
-
*/
|
|
52
|
-
export declare const buildTypeId: (baseId: string, version: number) => string;
|
|
53
57
|
/**
|
|
54
58
|
* Extract the base (family) ID from a TypeId, tolerating an already-bare
|
|
55
59
|
* baseId (no "@n" suffix) as a no-op. Used to compare across versions —
|
|
56
60
|
* e.g. a grant on "comment@1" and a record at "comment@2" share a baseId.
|
|
57
61
|
*/
|
|
58
62
|
export declare const baseIdOf: (typeId: string) => string;
|
|
63
|
+
/**
|
|
64
|
+
* Why `migratesFrom` cannot be the lineage of `id`, or null if it can. A
|
|
65
|
+
* version migrates from an earlier version of its own family; a step into
|
|
66
|
+
* another family is a migration, not lineage. See docs/spec/data-model.md
|
|
67
|
+
* § Type migrations.
|
|
68
|
+
*/
|
|
69
|
+
export declare const lineageProblem: (id: string, migratesFrom: unknown) => string | null;
|
|
59
70
|
/**
|
|
60
71
|
* Why `value` cannot name a type family, or null if it can. A family is a
|
|
61
72
|
* bare `BaseId`; a versioned TypeId names one version and is refused with the
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,kBAAkB,CAAC;AAC9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAqE3D;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,UAAU,KAAG,OAAO,CAAC,MAAM,CAMnE,CAAC;AAmFF;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GACvB,iBAAiB,kBAAkB,EACnC,gBAAgB,kBAAkB,KACjC,OAA8F,CAAC;AASlG,MAAM,MAAM,oBAAoB,GAAG;IACjC,qHAAqH;IACrH,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAmGF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,UAAU,EAAE,WAAW,UAAU,KAAG,oBAAoB,EAI3F,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,kBAAkB,KAAG,MAAM,EAGrC,CAAC;AAM7B;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAIlF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,QAAQ,MAAM,KAAG,MAA+C,CAAC;AAE1F;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,MAAM,EAAE,cAAc,OAAO,KAAG,MAAM,GAAG,IAW3E,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,EAAE,OAAO,MAAM,KAAG,MAAM,GAAG,IAWxE,CAAC"}
|
package/dist/schema.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stack — Schema Utilities
|
|
3
3
|
* -------------------------------------------------------
|
|
4
|
-
*
|
|
4
|
+
* What can be said about a TypeSchema and a TypeId without a stack: a
|
|
5
|
+
* schema's hash, whether one schema reads as another, whether one is a
|
|
6
|
+
* legal in-place evolution of another, and how a TypeId splits into its
|
|
7
|
+
* family and version.
|
|
5
8
|
*
|
|
6
9
|
* Hashing produces a stable SHA-256 fingerprint of a TypeSchema
|
|
7
10
|
* by canonicalizing it first (alphabetical keys, minified JSON).
|
|
8
11
|
* This is used for drift detection — not type identity, which is
|
|
9
12
|
* the namespaced ID controlled by the app author.
|
|
10
13
|
*/
|
|
14
|
+
import { formatEnumValues } from './validate.js';
|
|
11
15
|
// -------------------------------------------------------
|
|
12
16
|
// Canonical schema serialization
|
|
13
17
|
// -------------------------------------------------------
|
|
@@ -51,11 +55,11 @@ const canonicalizeFieldDef = (def) => {
|
|
|
51
55
|
...(def.required !== undefined && { required: def.required }),
|
|
52
56
|
};
|
|
53
57
|
}
|
|
54
|
-
// Scalar.
|
|
58
|
+
// Scalar. An enum's `values` are sorted so reordering them is not a change.
|
|
55
59
|
return {
|
|
56
|
-
...(def.kind === 'string' && def.enum && { enum: [...def.enum].sort() }),
|
|
57
60
|
kind: def.kind,
|
|
58
61
|
...(def.required !== undefined && { required: def.required }),
|
|
62
|
+
...(def.kind === 'enum' && { values: [...def.values].sort() }),
|
|
59
63
|
};
|
|
60
64
|
};
|
|
61
65
|
const canonicalizeSchema = (schema) => {
|
|
@@ -83,20 +87,22 @@ export const hashSchema = async (schema) => {
|
|
|
83
87
|
// -------------------------------------------------------
|
|
84
88
|
/**
|
|
85
89
|
* Kinds acceptable in a candidate field, per required kind. `string` and
|
|
86
|
-
* `text` are mutually acceptable for reading
|
|
87
|
-
*
|
|
90
|
+
* `text` are mutually acceptable for reading, and either accepts an enum,
|
|
91
|
+
* whose values are strings; everything else requires an exact match. A
|
|
92
|
+
* required enum takes the subset rule in isFieldCompatible instead. See
|
|
93
|
+
* docs/spec/data-model.md § Type compatibility.
|
|
88
94
|
*/
|
|
89
95
|
const READ_COMPATIBLE = {
|
|
90
|
-
string: ['string', 'text'],
|
|
91
|
-
text: ['text', 'string'],
|
|
96
|
+
string: ['string', 'text', 'enum'],
|
|
97
|
+
text: ['text', 'string', 'enum'],
|
|
92
98
|
number: ['number'],
|
|
93
99
|
boolean: ['boolean'],
|
|
94
100
|
date: ['date'],
|
|
95
101
|
'record-ref': ['record-ref'],
|
|
96
102
|
'file-ref': ['file-ref'],
|
|
97
103
|
};
|
|
98
|
-
// Candidate schemas can come from another app's Type definition
|
|
99
|
-
//
|
|
104
|
+
// Candidate schemas can come from another app's Type definition, whose
|
|
105
|
+
// shape validation bounds its depth, so recursion into array
|
|
100
106
|
// items / object properties is depth-bounded — matches MAX_VALIDATION_DEPTH
|
|
101
107
|
// in validate.ts. Past the limit we can't verify compatibility, so we
|
|
102
108
|
// fail closed (treat as incompatible) rather than risk a stack overflow.
|
|
@@ -132,6 +138,13 @@ const isFieldCompatible = (candidate, required, depth) => {
|
|
|
132
138
|
}
|
|
133
139
|
if (candidate.kind === 'array' || candidate.kind === 'object')
|
|
134
140
|
return false;
|
|
141
|
+
// A consumer expecting an enum can handle only the values it lists.
|
|
142
|
+
if (required.kind === 'enum') {
|
|
143
|
+
if (candidate.kind !== 'enum')
|
|
144
|
+
return false;
|
|
145
|
+
const allowed = new Set(required.values);
|
|
146
|
+
return candidate.values.every((v) => allowed.has(v));
|
|
147
|
+
}
|
|
135
148
|
return READ_COMPATIBLE[required.kind].includes(candidate.kind);
|
|
136
149
|
};
|
|
137
150
|
const isCompatibleAtDepth = (candidateSchema, requiredSchema, depth) => {
|
|
@@ -162,7 +175,10 @@ const diffField = (path, stored, candidate, depth, violations) => {
|
|
|
162
175
|
violations.push({ path, message: 'exceeds max nesting depth; cannot verify additive change' });
|
|
163
176
|
return;
|
|
164
177
|
}
|
|
165
|
-
|
|
178
|
+
// An enum becoming a string accepts strictly more, so it is the one kind
|
|
179
|
+
// change that is additive.
|
|
180
|
+
const widensEnum = stored.kind === 'enum' && candidate.kind === 'string';
|
|
181
|
+
if (stored.kind !== candidate.kind && !widensEnum) {
|
|
166
182
|
violations.push({
|
|
167
183
|
path,
|
|
168
184
|
message: `kind changed from "${stored.kind}" to "${candidate.kind}"`,
|
|
@@ -175,21 +191,12 @@ const diffField = (path, stored, candidate, depth, violations) => {
|
|
|
175
191
|
message: `required changed from ${!!stored.required} to ${!!candidate.required}`,
|
|
176
192
|
});
|
|
177
193
|
}
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
else if (stored.enum && candidate.enum) {
|
|
185
|
-
const kept = new Set(candidate.enum);
|
|
186
|
-
const removed = stored.enum.filter((v) => !kept.has(v));
|
|
187
|
-
if (removed.length > 0) {
|
|
188
|
-
violations.push({
|
|
189
|
-
path,
|
|
190
|
-
message: `enum values removed: ${removed.map((v) => JSON.stringify(v)).join(', ')}`,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
194
|
+
// Losing a value narrows what an enum accepts; gaining one widens it.
|
|
195
|
+
if (stored.kind === 'enum' && candidate.kind === 'enum') {
|
|
196
|
+
const kept = new Set(candidate.values);
|
|
197
|
+
const removed = stored.values.filter((v) => !kept.has(v));
|
|
198
|
+
if (removed.length > 0) {
|
|
199
|
+
violations.push({ path, message: `enum values removed: ${formatEnumValues(removed)}` });
|
|
193
200
|
}
|
|
194
201
|
}
|
|
195
202
|
// Opening a declared container, or closing an open one, changes which
|
|
@@ -252,6 +259,14 @@ export const diffSchemas = (stored, candidate) => {
|
|
|
252
259
|
diffFields('', stored, candidate, 0, violations);
|
|
253
260
|
return violations;
|
|
254
261
|
};
|
|
262
|
+
/**
|
|
263
|
+
* A schema's top-level `file-ref` fields — the content half of what a
|
|
264
|
+
* record references, beside its attachment associations. A nested one is
|
|
265
|
+
* validated but is not a reference. See docs/spec/data-model.md § Types.
|
|
266
|
+
*/
|
|
267
|
+
export const fileRefFields = (schema) => Object.entries(schema)
|
|
268
|
+
.filter(([, def]) => def.kind === 'file-ref')
|
|
269
|
+
.map(([field]) => field);
|
|
255
270
|
// -------------------------------------------------------
|
|
256
271
|
// Type ID parsing
|
|
257
272
|
// -------------------------------------------------------
|
|
@@ -266,17 +281,31 @@ export const parseTypeId = (typeId) => {
|
|
|
266
281
|
return null;
|
|
267
282
|
return { baseId: match[1], version: parseInt(match[2], 10) };
|
|
268
283
|
};
|
|
269
|
-
/**
|
|
270
|
-
* Build a versioned TypeId from a base ID and version number.
|
|
271
|
-
* e.g. ("com.example.myapp/note", 2) → "com.example.myapp/note@2"
|
|
272
|
-
*/
|
|
273
|
-
export const buildTypeId = (baseId, version) => `${baseId}@${version}`;
|
|
274
284
|
/**
|
|
275
285
|
* Extract the base (family) ID from a TypeId, tolerating an already-bare
|
|
276
286
|
* baseId (no "@n" suffix) as a no-op. Used to compare across versions —
|
|
277
287
|
* e.g. a grant on "comment@1" and a record at "comment@2" share a baseId.
|
|
278
288
|
*/
|
|
279
289
|
export const baseIdOf = (typeId) => parseTypeId(typeId)?.baseId ?? typeId;
|
|
290
|
+
/**
|
|
291
|
+
* Why `migratesFrom` cannot be the lineage of `id`, or null if it can. A
|
|
292
|
+
* version migrates from an earlier version of its own family; a step into
|
|
293
|
+
* another family is a migration, not lineage. See docs/spec/data-model.md
|
|
294
|
+
* § Type migrations.
|
|
295
|
+
*/
|
|
296
|
+
export const lineageProblem = (id, migratesFrom) => {
|
|
297
|
+
if (migratesFrom === undefined)
|
|
298
|
+
return null;
|
|
299
|
+
const self = parseTypeId(id);
|
|
300
|
+
const from = typeof migratesFrom === 'string' ? parseTypeId(migratesFrom) : null;
|
|
301
|
+
if (!self || !from) {
|
|
302
|
+
return `migratesFrom must be a versioned TypeId, e.g. "com.example.myapp/note@1".`;
|
|
303
|
+
}
|
|
304
|
+
if (from.baseId !== self.baseId || from.version >= self.version) {
|
|
305
|
+
return `"${id}" cannot migrate from "${migratesFrom}": migratesFrom names an earlier version of the same family.`;
|
|
306
|
+
}
|
|
307
|
+
return null;
|
|
308
|
+
};
|
|
280
309
|
/**
|
|
281
310
|
* Why `value` cannot name a type family, or null if it can. A family is a
|
|
282
311
|
* bare `BaseId`; a versioned TypeId names one version and is refused with the
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authority snapshot
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The authority one request acts with, read once: the `_grant` Records,
|
|
5
|
+
* the roles the subject holds on rosters, and the reach each verb builds
|
|
6
|
+
* from them — each loaded on first use and shared after, so an operation
|
|
7
|
+
* reads each at most once however many Records it decides. An operation
|
|
8
|
+
* takes its own and drops it when done; a subscription holds one for its
|
|
9
|
+
* life, which is only safe because every write that can move it arrives as
|
|
10
|
+
* an event that clears it. See docs/spec/access-control.md § Reach.
|
|
11
|
+
*/
|
|
12
|
+
import type { RosterRoles } from '../access.js';
|
|
13
|
+
import type { Reach, StackRecord } from '../types/index.js';
|
|
14
|
+
/** The verbs a reach is built for: one per thing a request can do to a Record. */
|
|
15
|
+
export type ReachVerb = 'create' | 'read' | 'update' | 'delete';
|
|
16
|
+
export type AuthoritySources = {
|
|
17
|
+
grants: () => Promise<StackRecord[]>;
|
|
18
|
+
roles: RosterRoles;
|
|
19
|
+
reach: (verb: ReachVerb, snapshot: AuthoritySnapshot) => Promise<Reach>;
|
|
20
|
+
};
|
|
21
|
+
export declare class AuthoritySnapshot {
|
|
22
|
+
private readonly sources;
|
|
23
|
+
private readonly grantSet;
|
|
24
|
+
private readonly roleSet;
|
|
25
|
+
private readonly reaches;
|
|
26
|
+
constructor(sources: AuthoritySources);
|
|
27
|
+
readonly grants: () => Promise<StackRecord[]>;
|
|
28
|
+
readonly roles: RosterRoles;
|
|
29
|
+
reach(verb: ReachVerb): Promise<Reach>;
|
|
30
|
+
/**
|
|
31
|
+
* Drop whatever a change to `typeFamily` can move, and every reach built
|
|
32
|
+
* from it. A load already in flight still answers the event that started
|
|
33
|
+
* it, which precedes the write; the next question loads afresh.
|
|
34
|
+
*/
|
|
35
|
+
invalidateFor(typeFamily: string): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=authority-snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authority-snapshot.d.ts","sourceRoot":"","sources":["../../src/scoped-stack/authority-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE5D,kFAAkF;AAClF,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACrC,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;CACzE,CAAC;AAEF,qBAAa,iBAAiB;IAKhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;gBAEhC,OAAO,EAAE,gBAAgB;IAKtD,QAAQ,CAAC,MAAM,QAAO,OAAO,CAAC,WAAW,EAAE,CAAC,CAAwB;IACpE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAA4B;IAEvD,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC;IAStC;;;;OAIG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAMxC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authority snapshot
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* The authority one request acts with, read once: the `_grant` Records,
|
|
5
|
+
* the roles the subject holds on rosters, and the reach each verb builds
|
|
6
|
+
* from them — each loaded on first use and shared after, so an operation
|
|
7
|
+
* reads each at most once however many Records it decides. An operation
|
|
8
|
+
* takes its own and drops it when done; a subscription holds one for its
|
|
9
|
+
* life, which is only safe because every write that can move it arrives as
|
|
10
|
+
* an event that clears it. See docs/spec/access-control.md § Reach.
|
|
11
|
+
*/
|
|
12
|
+
import { Lazy } from '../lazy.js';
|
|
13
|
+
import { SYSTEM_TYPES } from '../types/index.js';
|
|
14
|
+
export class AuthoritySnapshot {
|
|
15
|
+
sources;
|
|
16
|
+
grantSet;
|
|
17
|
+
roleSet;
|
|
18
|
+
reaches = new Map();
|
|
19
|
+
constructor(sources) {
|
|
20
|
+
this.sources = sources;
|
|
21
|
+
this.grantSet = new Lazy(sources.grants);
|
|
22
|
+
this.roleSet = new Lazy(sources.roles);
|
|
23
|
+
}
|
|
24
|
+
grants = () => this.grantSet.get();
|
|
25
|
+
roles = () => this.roleSet.get();
|
|
26
|
+
reach(verb) {
|
|
27
|
+
let reach = this.reaches.get(verb);
|
|
28
|
+
if (!reach) {
|
|
29
|
+
reach = new Lazy(() => this.sources.reach(verb, this));
|
|
30
|
+
this.reaches.set(verb, reach);
|
|
31
|
+
}
|
|
32
|
+
return reach.get();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Drop whatever a change to `typeFamily` can move, and every reach built
|
|
36
|
+
* from it. A load already in flight still answers the event that started
|
|
37
|
+
* it, which precedes the write; the next question loads afresh.
|
|
38
|
+
*/
|
|
39
|
+
invalidateFor(typeFamily) {
|
|
40
|
+
if (typeFamily === SYSTEM_TYPES.GRANT)
|
|
41
|
+
this.grantSet.clear();
|
|
42
|
+
else if (typeFamily === SYSTEM_TYPES.GROUP)
|
|
43
|
+
this.roleSet.clear();
|
|
44
|
+
else
|
|
45
|
+
return;
|
|
46
|
+
this.reaches.clear();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=authority-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authority-snapshot.js","sourceRoot":"","sources":["../../src/scoped-stack/authority-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAajD,MAAM,OAAO,iBAAiB;IAKC;IAJZ,QAAQ,CAAsB;IAC9B,OAAO,CAAyC;IAChD,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAE7D,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;QACpD,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAEQ,MAAM,GAAG,GAA2B,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAC3D,KAAK,GAAgB,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAEvD,KAAK,CAAC,IAAe;QACnB,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YACvD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,UAAkB;QAC9B,IAAI,UAAU,KAAK,YAAY,CAAC,KAAK;YAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;aACxD,IAAI,UAAU,KAAK,YAAY,CAAC,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;;YAC5D,OAAO;QACZ,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope authority
|
|
3
|
+
* -------------------------------------------------------
|
|
4
|
+
* What one (principal, subject) pair may do, as questions with yes-or-no
|
|
5
|
+
* answers: may this request read the record, create this type, reshare,
|
|
6
|
+
* reach this file. ScopedStack turns the answers into refusals and
|
|
7
|
+
* forwards what passes to its Stack; nothing here throws a refusal or
|
|
8
|
+
* writes. See docs/spec/access-control.md § Delegation: principal and
|
|
9
|
+
* subject.
|
|
10
|
+
*/
|
|
11
|
+
import type { ReachedRecord } from '../adapter/reach.js';
|
|
12
|
+
import { StackError } from '../errors.js';
|
|
13
|
+
import type { SplitQuery } from '../query-validation.js';
|
|
14
|
+
import { AuthoritySnapshot } from './authority-snapshot.js';
|
|
15
|
+
import type { ReachVerb } from './authority-snapshot.js';
|
|
16
|
+
import type { Actor, EntityId, QueryResult, Reach, StackRecord, TypeId } from '../types/index.js';
|
|
17
|
+
import type { Stack } from '../stack/stack.js';
|
|
18
|
+
export declare class ScopeAuthority {
|
|
19
|
+
private readonly stack;
|
|
20
|
+
/** Whose grants bound what this request may do — see ScopedStack.principalId. */
|
|
21
|
+
readonly principalId: EntityId | null;
|
|
22
|
+
/** Whom this request acts for and attributes writes to — see ScopedStack.subjectId. */
|
|
23
|
+
readonly subjectId: EntityId | null;
|
|
24
|
+
/** Stack.query() within a reach — see ScopedStack.query(). */
|
|
25
|
+
private readonly queryReadable;
|
|
26
|
+
constructor(stack: Stack,
|
|
27
|
+
/** Whose grants bound what this request may do — see ScopedStack.principalId. */
|
|
28
|
+
principalId: EntityId | null,
|
|
29
|
+
/** Whom this request acts for and attributes writes to — see ScopedStack.subjectId. */
|
|
30
|
+
subjectId: EntityId | null,
|
|
31
|
+
/** Stack.query() within a reach — see ScopedStack.query(). */
|
|
32
|
+
queryReadable: (split: SplitQuery, reach: Reach) => Promise<QueryResult>);
|
|
33
|
+
/**
|
|
34
|
+
* The authority this request acts with, for one operation: pass it to
|
|
35
|
+
* each check the operation makes, so the grants, the rosters and each
|
|
36
|
+
* verb's reach are read at most once. An anonymous request is named by no
|
|
37
|
+
* grant and held by no roster, so it reads neither.
|
|
38
|
+
*/
|
|
39
|
+
snapshot(): AuthoritySnapshot;
|
|
40
|
+
/** Whether a delegated app is acting for someone other than itself. */
|
|
41
|
+
get delegated(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether any grant could name this request — the one question every
|
|
44
|
+
* prefetch asks before scanning the `_grant` family, since an anonymous
|
|
45
|
+
* requester is reached by none. Both identities are read: `asEntity()`
|
|
46
|
+
* refuses an anonymous principal acting for a subject, so they are null
|
|
47
|
+
* together, and saying so costs nothing.
|
|
48
|
+
*/
|
|
49
|
+
get identified(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Who this request is, for stamping onto whatever it mutates. Attribution
|
|
52
|
+
* follows record-level authorship: the subject is the actor, and the
|
|
53
|
+
* principal is named beside it only when the two differ.
|
|
54
|
+
* See docs/spec/data-model.md § Authorship and attribution.
|
|
55
|
+
*/
|
|
56
|
+
get requester(): Actor | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Whether unconditional owner authority applies — the owner acting as
|
|
59
|
+
* itself. The verbs resting on it are irreversible or disclose the sharing
|
|
60
|
+
* graph, so delegation never carries it, whichever side the owner is on.
|
|
61
|
+
* See docs/spec/access-control.md § Delegation: principal and subject.
|
|
62
|
+
*/
|
|
63
|
+
get ownerActingAlone(): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Whether no grant bounds the principal: undelegated, it is the subject
|
|
66
|
+
* itself, and the owner as principal is the owner's own software.
|
|
67
|
+
* See docs/spec/access-control.md § Delegation: principal and subject.
|
|
68
|
+
*/
|
|
69
|
+
private get principalUnbounded();
|
|
70
|
+
/**
|
|
71
|
+
* The families `grantee`'s grants convey one of `actions` on, read the way
|
|
72
|
+
* `side` reads a grant. Only the subject's side counts a group, so the
|
|
73
|
+
* rosters read are always the subject's.
|
|
74
|
+
* See docs/spec/access-control.md § Who a grant reaches.
|
|
75
|
+
*/
|
|
76
|
+
private familiesConveying;
|
|
77
|
+
/**
|
|
78
|
+
* What this request may do with `verb` — that verb's rules, built whole
|
|
79
|
+
* even where a Record's own permissions would settle it, since every gate
|
|
80
|
+
* asks one value at a flat cost. The principal's grants fence it; within,
|
|
81
|
+
* the subject reaches what grants and permissions give it, an owner
|
|
82
|
+
* subject everything. See docs/spec/access-control.md § Reach.
|
|
83
|
+
*/
|
|
84
|
+
private buildReach;
|
|
85
|
+
/**
|
|
86
|
+
* The permission elements carrying `bit` to the subject, as the sets a
|
|
87
|
+
* Record must hold whole. A `read` stands alone, as does `anyone`; a
|
|
88
|
+
* `write` stands beside one of its readCompanions().
|
|
89
|
+
*/
|
|
90
|
+
private elementSets;
|
|
91
|
+
/** Whether this request may `verb` the Record: its reach, asked of one Record. */
|
|
92
|
+
may(verb: ReachVerb, record: ReachedRecord, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
93
|
+
/**
|
|
94
|
+
* may() with the principal's fence set aside — whether the subject alone
|
|
95
|
+
* reaches the Record, for a refusal that says which side lacked the verb.
|
|
96
|
+
*/
|
|
97
|
+
subjectMay(verb: ReachVerb, record: ReachedRecord, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
98
|
+
canRead(record: StackRecord, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
99
|
+
/** Whether this request may create a Record of the type, asked of the Record it would make. */
|
|
100
|
+
canCreate(typeId: TypeId, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
101
|
+
/**
|
|
102
|
+
* How to refuse a record this request addressed by ID: a permission error
|
|
103
|
+
* to a requester who can read it, the not-found answer to anyone else, so
|
|
104
|
+
* `message` only reaches someone holding the record already.
|
|
105
|
+
* See docs/spec/disclosure.md § Which refusal a Record answers with.
|
|
106
|
+
*/
|
|
107
|
+
denialFor(record: StackRecord, message: string, snapshot: AuthoritySnapshot): Promise<StackError>;
|
|
108
|
+
/**
|
|
109
|
+
* `_group` records are managed, not merely written: only the owner or an
|
|
110
|
+
* `admin` roster holder may mutate them — ordinary write permissions and
|
|
111
|
+
* grants don't apply. Asked of both identities under delegation, like
|
|
112
|
+
* a reshare. See docs/spec/identity.md § Group.
|
|
113
|
+
*/
|
|
114
|
+
isGroupManager(record: StackRecord): boolean;
|
|
115
|
+
/** Whether one identity, on its own, manages `record` — see isGroupManager(). */
|
|
116
|
+
private managesGroup;
|
|
117
|
+
/**
|
|
118
|
+
* Whether this request may reference `recordId` as a parent or target.
|
|
119
|
+
* Missing and unreadable are both false, so this probes nothing. The
|
|
120
|
+
* owner acting alone skips the lookup and leaves absence to `Stack`.
|
|
121
|
+
* See docs/spec/access-control.md § Reference-creation gating.
|
|
122
|
+
*/
|
|
123
|
+
canReadReferent(recordId: string, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* Whether this request can read some record referencing `fileId`, other
|
|
126
|
+
* than an `_attachment@1` record — otherwise one correct guess would
|
|
127
|
+
* unlock unlimited further metadata records for the file.
|
|
128
|
+
* See docs/spec/attachments.md § Creating `_attachment@1` records directly.
|
|
129
|
+
*/
|
|
130
|
+
hasReadableReference(fileId: string, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
131
|
+
/**
|
|
132
|
+
* Whether this request may reference or download `fileId` — the dual of
|
|
133
|
+
* getAttachment()'s access rule. Nonexistent and inaccessible are
|
|
134
|
+
* indistinguishable (both false), so no confirmation oracle for guessed
|
|
135
|
+
* hashes. See docs/spec/access-control.md § Reference-creation gating.
|
|
136
|
+
*/
|
|
137
|
+
canAccessFile(fileId: string, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
138
|
+
/**
|
|
139
|
+
* Whether this request is an installed app, acting as itself, migrating
|
|
140
|
+
* `record` within families its one live install claims, to a version the
|
|
141
|
+
* owner approved, holding `update-any` on each directly.
|
|
142
|
+
* See docs/spec/apps.md § Migrating an installed app's types.
|
|
143
|
+
*/
|
|
144
|
+
installMayMigrate(record: StackRecord, toTypeId: TypeId, snapshot: AuthoritySnapshot): Promise<boolean>;
|
|
145
|
+
/** Names of the type's top-level file-ref fields — the content-reference half of referencesFileId matching. */
|
|
146
|
+
fileRefFieldNames(typeId: TypeId): Promise<string[]>;
|
|
147
|
+
/**
|
|
148
|
+
* Whether this request may widen who reaches a record, at create time or
|
|
149
|
+
* after. A delegated app may not, unless the owner is its principal:
|
|
150
|
+
* widening access is what containment most needs to hold.
|
|
151
|
+
* See docs/spec/access-control.md § Delegation: principal and subject.
|
|
152
|
+
*/
|
|
153
|
+
mayGrantAccess(): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Whether one identity, on its own, may decide who else reaches `record`
|
|
156
|
+
* — the owner-or-creator rule a reshare enforces, asked of one
|
|
157
|
+
* side at a time. See
|
|
158
|
+
* docs/spec/access-control.md § Delegation: principal and subject.
|
|
159
|
+
*/
|
|
160
|
+
private mayReshare;
|
|
161
|
+
/**
|
|
162
|
+
* Whether this request may decide who else reaches `record`: management
|
|
163
|
+
* for a `_group`, so a demoted creator keeps no side door; otherwise the
|
|
164
|
+
* owner-or-author rule, asked of both sides of a delegation.
|
|
165
|
+
* See docs/spec/access-control.md § Record-level permissions.
|
|
166
|
+
*/
|
|
167
|
+
canReshare(record: StackRecord): boolean;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=authority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authority.d.ts","sourceRoot":"","sources":["../../src/scoped-stack/authority.ts"],"names":[],"mappings":"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"}
|