@haverstack/core 0.34.0 → 0.36.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 +1 -1
- package/dist/access.d.ts +39 -34
- package/dist/access.d.ts.map +1 -1
- package/dist/access.js +94 -68
- package/dist/access.js.map +1 -1
- package/dist/changes.d.ts +22 -33
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +34 -48
- package/dist/changes.js.map +1 -1
- package/dist/combine.d.ts.map +1 -1
- package/dist/combine.js +7 -0
- package/dist/combine.js.map +1 -1
- package/dist/grants.d.ts +78 -33
- package/dist/grants.d.ts.map +1 -1
- package/dist/grants.js +164 -72
- package/dist/grants.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/query-validation.d.ts +20 -1
- package/dist/query-validation.d.ts.map +1 -1
- package/dist/query-validation.js +107 -3
- package/dist/query-validation.js.map +1 -1
- package/dist/record-changes.d.ts +71 -63
- package/dist/record-changes.d.ts.map +1 -1
- package/dist/record-changes.js +129 -85
- package/dist/record-changes.js.map +1 -1
- package/dist/scoped-stack.d.ts +118 -116
- package/dist/scoped-stack.d.ts.map +1 -1
- package/dist/scoped-stack.js +210 -188
- package/dist/scoped-stack.js.map +1 -1
- package/dist/stack.d.ts +143 -160
- package/dist/stack.d.ts.map +1 -1
- package/dist/stack.js +271 -225
- package/dist/stack.js.map +1 -1
- package/dist/testing.d.ts +3 -8
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +42 -49
- package/dist/testing.js.map +1 -1
- package/dist/types.d.ts +128 -101
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +0 -2
- package/dist/validate.js.map +1 -1
- package/dist/wire-record.d.ts.map +1 -1
- package/dist/wire-record.js.map +1 -1
- package/package.json +1 -1
package/dist/grants.js
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
import { baseIdOf } from './schema.js';
|
|
12
12
|
import { StackQueryError } from './errors.js';
|
|
13
13
|
import { SYSTEM_TYPES, GRANT_ACTIONS } from './types.js';
|
|
14
|
-
import { groupRoleFromAssociations } from './access.js';
|
|
14
|
+
import { carriesRoster, groupRoleFromAssociations } from './access.js';
|
|
15
15
|
import { queryAllPages } from './stack-reads.js';
|
|
16
16
|
/**
|
|
17
|
-
* Valid GrantAction values, for runtime validation in Stack.grant().
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Valid GrantAction values, for runtime validation in Stack.grant(). Built
|
|
18
|
+
* from GRANT_ACTIONS, which GrantAction itself derives from, so the set and
|
|
19
|
+
* the type cannot drift.
|
|
20
20
|
*/
|
|
21
21
|
export const GRANT_ACTION_SET = new Set(GRANT_ACTIONS);
|
|
22
22
|
/**
|
|
@@ -35,11 +35,13 @@ export const READ_COMPANIONS = new Map([
|
|
|
35
35
|
]);
|
|
36
36
|
/**
|
|
37
37
|
* Whether one grant's action list conveys `action`. The companion has to
|
|
38
|
-
* sit in the same `_grant` Record
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
38
|
+
* sit in the same `_grant` Record: a grant is revoked whole, so a rule
|
|
39
|
+
* satisfied across two records would let revoking the read one leave a
|
|
40
|
+
* mutate-without-read grant standing.
|
|
41
|
+
*
|
|
42
|
+
* Takes the list grantReach() produced, never a stored field: `includes()`
|
|
43
|
+
* over a string is substring matching, so one would answer for every verb
|
|
44
|
+
* spelled inside it.
|
|
43
45
|
*/
|
|
44
46
|
export function grantConveys(actions, action) {
|
|
45
47
|
if (!actions.includes(action))
|
|
@@ -47,74 +49,166 @@ export function grantConveys(actions, action) {
|
|
|
47
49
|
const companions = READ_COMPANIONS.get(action);
|
|
48
50
|
return !companions || companions.some((c) => actions.includes(c));
|
|
49
51
|
}
|
|
50
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* What a stored `_grant` reaches, or null where it names nothing the
|
|
54
|
+
* evaluator recognizes. Read as data, like the grantee beside it: a grant
|
|
55
|
+
* Record can arrive from an import, a direct adapter write or a foreign
|
|
56
|
+
* server, where no schema saw it, so both fields are asked for their shape
|
|
57
|
+
* rather than taken from the type. An unknown action is dropped from the
|
|
58
|
+
* list, on the same terms an unknown grantee `kind` confers nothing.
|
|
59
|
+
* See docs/spec/access-control.md § Refused at the write, and again at evaluation.
|
|
60
|
+
*/
|
|
61
|
+
export function grantReach(content) {
|
|
62
|
+
const c = content;
|
|
63
|
+
if (!c || typeof c !== 'object')
|
|
64
|
+
return null;
|
|
65
|
+
if (typeof c.typeId !== 'string' || c.typeId.length === 0)
|
|
66
|
+
return null;
|
|
67
|
+
if (!Array.isArray(c.actions))
|
|
68
|
+
return null;
|
|
69
|
+
return {
|
|
70
|
+
familyId: baseIdOf(c.typeId),
|
|
71
|
+
actions: c.actions.filter((a) => GRANT_ACTION_SET.has(a)),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Direct (non-roster) match between a stored _grant's content and a target:
|
|
76
|
+
* the whole grantee, `role` included. A target is the identity grant()
|
|
77
|
+
* wrote, so a revoke aimed at a group's admins leaves the members' grant
|
|
78
|
+
* standing. A query's `role: 'any'` is the one widening, and it is spelled.
|
|
79
|
+
*/
|
|
51
80
|
export function matchesGrantTarget(content, target) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
const g = content.grantee;
|
|
82
|
+
if (!g || g.kind !== target.kind)
|
|
83
|
+
return false;
|
|
84
|
+
if (g.kind === 'entity')
|
|
85
|
+
return g.entityId === target.entityId;
|
|
86
|
+
if (g.kind === 'group') {
|
|
87
|
+
const t = target;
|
|
88
|
+
return g.groupId === t.groupId && (t.role === 'any' || g.role === t.role);
|
|
59
89
|
}
|
|
60
|
-
|
|
61
|
-
|
|
90
|
+
return g.kind === 'authenticated';
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Reject a grant target that names no tier, or whose tier names nobody. An
|
|
94
|
+
* empty groupId or entityId reaches no one, so storing it would leave a
|
|
95
|
+
* grant that can only ever deny while looking like a share that worked.
|
|
96
|
+
* Read as data, not as the type: a target reaching Stack from a request
|
|
97
|
+
* body or an import has whatever shape it arrived with. `allowAny` admits
|
|
98
|
+
* the listing-only `role: 'any'`, which grant() and revoke() refuse.
|
|
99
|
+
*/
|
|
100
|
+
export function validateGrantTarget(target, allowAny = false) {
|
|
101
|
+
const t = target;
|
|
102
|
+
switch (t?.kind) {
|
|
103
|
+
case 'authenticated':
|
|
104
|
+
return;
|
|
105
|
+
case 'entity':
|
|
106
|
+
if (typeof t.entityId !== 'string' || t.entityId.length === 0) {
|
|
107
|
+
throw new StackQueryError('An entity grant target requires a non-empty entityId.');
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
case 'group':
|
|
111
|
+
if (typeof t.groupId !== 'string' || t.groupId.length === 0) {
|
|
112
|
+
throw new StackQueryError('A group grant target requires a non-empty groupId.');
|
|
113
|
+
}
|
|
114
|
+
if (t.role !== 'member' && t.role !== 'admin' && !(allowAny && t.role === 'any')) {
|
|
115
|
+
throw new StackQueryError(allowAny
|
|
116
|
+
? "A group grant target requires role 'member', 'admin' or 'any'."
|
|
117
|
+
: "A group grant target requires role 'member' or 'admin'.");
|
|
118
|
+
}
|
|
119
|
+
// No format check: groupId is a reference, like parentId or an
|
|
120
|
+
// association's recordId. One that resolves to nothing simply denies.
|
|
121
|
+
return;
|
|
122
|
+
default:
|
|
123
|
+
throw new StackQueryError("A grant target must name its tier: { kind: 'entity' }, { kind: 'group' } or { kind: 'authenticated' }.");
|
|
62
124
|
}
|
|
63
|
-
return content.granteeEntityId === target;
|
|
64
125
|
}
|
|
65
126
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
127
|
+
* The fields each grantee arm must carry, asked of a `_grant`'s content on
|
|
128
|
+
* every write. The schema cannot ask it — a closed `object` field holds one
|
|
129
|
+
* `properties` set, so only `kind` is required there — and an arm missing
|
|
130
|
+
* its own field would otherwise store, answer 200, then deny forever.
|
|
70
131
|
*/
|
|
71
|
-
export function
|
|
72
|
-
if (
|
|
73
|
-
return;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
132
|
+
export function validateGrantee(typeId, content) {
|
|
133
|
+
if (baseIdOf(typeId) !== SYSTEM_TYPES.GRANT)
|
|
134
|
+
return [];
|
|
135
|
+
const c = content;
|
|
136
|
+
const g = c?.grantee;
|
|
137
|
+
// An absent or non-object grantee is the schema's to refuse, and it does.
|
|
138
|
+
if (!g || typeof g !== 'object')
|
|
139
|
+
return [];
|
|
140
|
+
switch (g.kind) {
|
|
141
|
+
case 'authenticated':
|
|
142
|
+
return [];
|
|
143
|
+
case 'entity':
|
|
144
|
+
return typeof g.entityId === 'string' && g.entityId.length > 0
|
|
145
|
+
? []
|
|
146
|
+
: [
|
|
147
|
+
{
|
|
148
|
+
path: 'grantee.entityId',
|
|
149
|
+
message: 'An entity grantee requires a non-empty entityId',
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
case 'group': {
|
|
153
|
+
const errors = [];
|
|
154
|
+
if (typeof g.groupId !== 'string' || g.groupId.length === 0) {
|
|
155
|
+
errors.push({
|
|
156
|
+
path: 'grantee.groupId',
|
|
157
|
+
message: 'A group grantee requires a non-empty groupId',
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (g.role !== 'member' && g.role !== 'admin') {
|
|
161
|
+
errors.push({
|
|
162
|
+
path: 'grantee.role',
|
|
163
|
+
message: "A group grantee requires role 'member' or 'admin'",
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return errors;
|
|
77
167
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
168
|
+
default:
|
|
169
|
+
return [
|
|
170
|
+
{
|
|
171
|
+
path: 'grantee.kind',
|
|
172
|
+
message: "A grantee must name its tier: 'entity', 'group' or 'authenticated'",
|
|
173
|
+
},
|
|
174
|
+
];
|
|
82
175
|
}
|
|
83
|
-
// Not a format check: granteeGroupId is a reference to an existing
|
|
84
|
-
// Record, like parentId or an association's recordId, and none of those
|
|
85
|
-
// are parsed either. One that resolves to nothing simply denies.
|
|
86
176
|
}
|
|
87
177
|
/**
|
|
88
178
|
* Whether a stored _grant covers `grantee`: a direct DID match, roster
|
|
89
|
-
* membership when `allowGroup`, or
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
179
|
+
* membership when `allowGroup`, or the authenticated tier when
|
|
180
|
+
* `allowDefault`. The grantee's own `kind` decides which question is asked
|
|
181
|
+
* — every tier is affirmative, and none is reachable by omission, so a
|
|
182
|
+
* grant carrying nothing recognizable confers nothing.
|
|
93
183
|
*/
|
|
94
184
|
export async function grantCoversGrantee(c, grantee, opts) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
if (!namesEntity && !namesGroup)
|
|
98
|
-
return opts.allowDefault;
|
|
99
|
-
if (namesEntity && c.granteeEntityId !== grantee)
|
|
185
|
+
const g = c.grantee;
|
|
186
|
+
if (!g || typeof g !== 'object')
|
|
100
187
|
return false;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return
|
|
104
|
-
|
|
105
|
-
return
|
|
106
|
-
|
|
107
|
-
|
|
188
|
+
switch (g.kind) {
|
|
189
|
+
case 'authenticated':
|
|
190
|
+
return opts.allowDefault;
|
|
191
|
+
case 'entity':
|
|
192
|
+
return !!g.entityId && g.entityId === grantee;
|
|
193
|
+
case 'group': {
|
|
194
|
+
if (!opts.allowGroup)
|
|
195
|
+
return false;
|
|
196
|
+
if (!g.groupId)
|
|
197
|
+
return false;
|
|
198
|
+
if (g.role !== 'member' && g.role !== 'admin')
|
|
199
|
+
return false;
|
|
200
|
+
const role = await resolveGroupRoleMemoized(g.groupId, grantee, opts.groupRoles, opts.resolveRecord);
|
|
201
|
+
return g.role === 'admin' ? role === 'admin' : role !== null;
|
|
202
|
+
}
|
|
203
|
+
default:
|
|
108
204
|
return false;
|
|
109
205
|
}
|
|
110
|
-
return true;
|
|
111
206
|
}
|
|
112
207
|
/**
|
|
113
208
|
* An entity's role on a `_group` roster, memoized in the caller's
|
|
114
|
-
* `groupRoles` map. That map is built per operation
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* See docs/spec/access-control.md § Type-level grants.
|
|
209
|
+
* `groupRoles` map. That map is built per operation, so no resolved role
|
|
210
|
+
* outlives the operation that resolved it — removal from a group must never
|
|
211
|
+
* go stale.
|
|
118
212
|
*/
|
|
119
213
|
async function resolveGroupRoleMemoized(groupId, entityId, groupRoles, resolveRecord) {
|
|
120
214
|
const key = `${groupId}:${entityId}`;
|
|
@@ -122,22 +216,15 @@ async function resolveGroupRoleMemoized(groupId, entityId, groupRoles, resolveRe
|
|
|
122
216
|
if (cached !== undefined)
|
|
123
217
|
return cached;
|
|
124
218
|
const group = await resolveRecord(groupId);
|
|
125
|
-
|
|
126
|
-
// any Record's relationship associations would serve as one, and a group
|
|
127
|
-
// migrated out of the family would keep resolving after it had stopped
|
|
128
|
-
// being a group.
|
|
129
|
-
const role = group && baseIdOf(group.typeId) === SYSTEM_TYPES.GROUP
|
|
130
|
-
? groupRoleFromAssociations(group.associations, entityId)
|
|
131
|
-
: null;
|
|
219
|
+
const role = group && carriesRoster(group) ? groupRoleFromAssociations(group.associations, entityId) : null;
|
|
132
220
|
groupRoles.set(key, role);
|
|
133
221
|
return role;
|
|
134
222
|
}
|
|
135
223
|
/**
|
|
136
224
|
* System type families grant() refuses to target: a grant on any of them
|
|
137
225
|
* would let the grantee mint their own grants, touch stack config, or
|
|
138
|
-
* register an app card claiming a DID that isn't theirs — the last of
|
|
139
|
-
*
|
|
140
|
-
* docs/spec/access-control.md § Type-level grants.
|
|
226
|
+
* register an app card claiming a DID that isn't theirs — the last of which
|
|
227
|
+
* is what verified app attribution rests on.
|
|
141
228
|
*/
|
|
142
229
|
export const UNGRANTABLE_SYSTEM_TYPES = new Set([
|
|
143
230
|
SYSTEM_TYPES.GRANT,
|
|
@@ -147,11 +234,16 @@ export const UNGRANTABLE_SYSTEM_TYPES = new Set([
|
|
|
147
234
|
/**
|
|
148
235
|
* Every `_grant` Record, cursor-walked. Read through an unscoped query at
|
|
149
236
|
* every call site: a grant is what decides who may read, so it can never
|
|
150
|
-
* itself sit behind a read check.
|
|
151
|
-
*
|
|
152
|
-
*
|
|
237
|
+
* itself sit behind a read check.
|
|
238
|
+
*
|
|
239
|
+
* `includeUnlisted`, because withholding a Record from enumeration decides
|
|
240
|
+
* nothing about what it confers. Deleted grants are excluded on the
|
|
241
|
+
* opposite grounds — a soft delete is how revoke() withdraws one.
|
|
242
|
+
* See docs/spec/unlisted.md.
|
|
153
243
|
*/
|
|
154
244
|
export function loadGrantRecords(query) {
|
|
155
|
-
return queryAllPages(query, {
|
|
245
|
+
return queryAllPages(query, {
|
|
246
|
+
filter: { typeId: `${SYSTEM_TYPES.GRANT}@1`, includeUnlisted: true },
|
|
247
|
+
});
|
|
156
248
|
}
|
|
157
249
|
//# sourceMappingURL=grants.js.map
|
package/dist/grants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grants.js","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"grants.js","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,8 @@ export { ScopedStack } from './scoped-stack.js';
|
|
|
19
19
|
export type { StackClient, CreateRecordOptions, BackdatableCreateRecordOptions, StackOptions, GetRecordOptions, DeleteRecordOptions, DeleteResult, IfVersionOptions, CollectAttachmentGarbageOptions, CollectAttachmentGarbageResult, } from './stack.js';
|
|
20
20
|
export { StackError, StackValidationError, StackMigrationError, StackPermissionError, StackNotFoundError, StackConflictError, StackVersionConflictError, StackQueryError, StackSchemaDriftError, StackPayloadTooLargeError, StackTimeoutError, StackClosedError, StackRelayScopeError, } from './errors.js';
|
|
21
21
|
export type { StackErrorCode } from './errors.js';
|
|
22
|
-
export type { RecordId, TypeId, FileId, EntityId, AttachmentContent, StackRecord, RecordChanges, RecordVersion, RecordJournalEntry, JournalEntryInput, JournalOptions, JournalQuery, ActorOptions, ChangeKind, ChangeOp, ChangeActor, RecordChange, ChangeFilter, SubscribeOptions, Unsubscribe, ExpectedVersionOptions, SnapshotOptions, BumpVersionOptions, StackType, TypeSchema, FieldDef, ScalarFieldDef, ArrayFieldDef, ObjectFieldDef, ScalarFieldKind, Association, TagAssociation, AttachmentAssociation, RelationshipAssociation, AssociationChange, RelationshipTarget, RecordTarget, EntityTarget, ExternalTarget,
|
|
22
|
+
export type { RecordId, TypeId, FileId, EntityId, AttachmentContent, StackRecord, RecordChanges, RecordVersion, RecordJournalEntry, JournalEntryInput, JournalOptions, JournalQuery, ActorOptions, ChangeKind, ChangeOp, ChangeActor, RecordChange, ChangeFilter, SubscribeOptions, Unsubscribe, ExpectedVersionOptions, SnapshotOptions, BumpVersionOptions, StackType, TypeSchema, FieldDef, ScalarFieldDef, ArrayFieldDef, ObjectFieldDef, ScalarFieldKind, Association, TagAssociation, AttachmentAssociation, RelationshipAssociation, PermissionAssociation, PermissionGrantee, AnyoneAssociation, AuthorityAssociation, DataAssociation, AssociationChange, RelationshipTarget, RecordTarget, EntityTarget, ExternalTarget, StackQuery, RecordFilter, RelatedToFilter, RelationshipTargetPattern, QuerySort, NativeSortField, ContentFilterReach, MissingCapability, QueryResult, DateRange, Migration, MigrationFn, StackAdapter, StackFeatures, TokenSession, EntityContent, AppContent, GroupContent, GrantAction, GrantContent, GrantGrantee, ConfigContent, } from './types.js';
|
|
23
|
+
export type { GrantQuery } from './grants.js';
|
|
23
24
|
export { SYSTEM_TYPES, NATIVE_SORT_FIELDS } from './types.js';
|
|
24
25
|
export { generateId } from './id.js';
|
|
25
26
|
export { hashSchema, isCompatible } from './schema.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,8BAA8B,EAC9B,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,YAAY,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,8BAA8B,EAC9B,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,YAAY,EACV,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,EACZ,eAAe,EACf,yBAAyB,EACzB,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAM9D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kCAAkC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAchD,qBAAqB;AACrB,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kCAAkC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAchD,qBAAqB;AACrB,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AA2ErB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE9D,YAAY;AAEZ,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* See docs/spec/data-model.md § Capability-gated filters.
|
|
18
18
|
*/
|
|
19
19
|
import type { ValidationError } from './validate.js';
|
|
20
|
-
import type { Association, JournalQuery, QuerySort, RecordFilter, StackFeatures } from './types.js';
|
|
20
|
+
import type { Association, AuthorityAssociation, DataAssociation, JournalQuery, QuerySort, RecordFilter, StackFeatures } from './types.js';
|
|
21
21
|
/**
|
|
22
22
|
* Fail loud rather than silently widen: a filter the adapter can't honor
|
|
23
23
|
* would otherwise be dropped, returning an unfiltered superset presented
|
|
@@ -70,6 +70,25 @@ export declare function assertSortCapability(sort: QuerySort | undefined, capabi
|
|
|
70
70
|
* § Relationship targets.
|
|
71
71
|
*/
|
|
72
72
|
export declare function validateAssociation(association: Association, path?: string): ValidationError[];
|
|
73
|
+
/**
|
|
74
|
+
* Refuse an authority element reaching the data half of the partition.
|
|
75
|
+
* The two share a table, a delta shape and a durability tier; they never
|
|
76
|
+
* share a call, because an app editing tags would otherwise be able to
|
|
77
|
+
* replace an ACL it was never shown. Thrown rather than collected: the
|
|
78
|
+
* caller named the wrong surface, not a malformed value, and the verb it
|
|
79
|
+
* wanted is `grantAccess()`/`revokeAccess()`.
|
|
80
|
+
*
|
|
81
|
+
* Lives here, in the invariant layer, so an unscoped `Stack`, an import
|
|
82
|
+
* and a server mapping a request body are all held to it.
|
|
83
|
+
* See docs/spec/access-control.md § Record-level permissions.
|
|
84
|
+
*/
|
|
85
|
+
export declare function assertDataAssociations(associations: readonly Association[], surface: string): asserts associations is DataAssociation[];
|
|
86
|
+
/**
|
|
87
|
+
* The mirror of assertDataAssociations(): the `permissions` surface takes
|
|
88
|
+
* authority kinds alone, so a tag routed through it is refused rather than
|
|
89
|
+
* quietly becoming an ACL entry the `associations` projection never shows.
|
|
90
|
+
*/
|
|
91
|
+
export declare function assertAuthorityAssociations(permissions: readonly Association[], surface: string): asserts permissions is AuthorityAssociation[];
|
|
73
92
|
/** validateAssociation() over a create's `associations` array. */
|
|
74
93
|
/**
|
|
75
94
|
* Every association in a list, plus the one rule a list has that a single
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-validation.d.ts","sourceRoot":"","sources":["../src/query-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EACV,WAAW,EACX,YAAY,
|
|
1
|
+
{"version":3,"file":"query-validation.d.ts","sourceRoot":"","sources":["../src/query-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,YAAY,EAEZ,SAAS,EACT,YAAY,EAGZ,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,GAAG,SAAS,EAChC,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAC1C,IAAI,CAmCN;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,GAAG,OAAO,CAE/E;AAKD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB3D;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CA2BjE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,GAAG,SAAS,EAC3B,YAAY,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GACxC,IAAI,CAmBN;AA0CD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,IAAI,SAAgB,GACnB,eAAe,EAAE,CAmBnB;AAoED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,SAAS,WAAW,EAAE,EACpC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,IAAI,eAAe,EAAE,CAO3C;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,SAAS,WAAW,EAAE,EACnC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,IAAI,oBAAoB,EAAE,CAO/C;AAED,kEAAkE;AAClE;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,WAAW,EAAE,GAAG,SAAS,EACvC,IAAI,SAAiB,GACpB,eAAe,EAAE,CAenB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,YAAY,CAAC,WAAW,CAAC,GAAG,IAAI,CAY/E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAW7E"}
|
package/dist/query-validation.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* See docs/spec/data-model.md § Capability-gated filters.
|
|
18
18
|
*/
|
|
19
19
|
import { StackQueryError } from './errors.js';
|
|
20
|
-
import { associationEqual } from './record-changes.js';
|
|
20
|
+
import { associationEqual, isAuthorityAssociation } from './record-changes.js';
|
|
21
21
|
import { CONTENT_SEGMENT_METACHARACTERS, SEGMENT_METACHARACTER_RE } from './validate.js';
|
|
22
22
|
import { NATIVE_SORT_FIELDS } from './types.js';
|
|
23
23
|
/**
|
|
@@ -197,10 +197,114 @@ function targetErrors(target, path, opts = {}) {
|
|
|
197
197
|
* § Relationship targets.
|
|
198
198
|
*/
|
|
199
199
|
export function validateAssociation(association, path = 'association') {
|
|
200
|
-
if (association
|
|
200
|
+
if (!namesKind(association)) {
|
|
201
|
+
return [
|
|
202
|
+
{
|
|
203
|
+
path: `${path}.kind`,
|
|
204
|
+
message: `Unknown association kind "${String(association?.kind)}": expected ${[...ASSOCIATION_KINDS].map((k) => `"${k}"`).join(', ')}.`,
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
if (association.kind === 'permission') {
|
|
209
|
+
return granteeErrors(association, `${path}.grantee`);
|
|
210
|
+
}
|
|
211
|
+
if (association.kind === 'anyone') {
|
|
212
|
+
return association.label === 'read'
|
|
213
|
+
? []
|
|
214
|
+
: [{ path: `${path}.label`, message: 'An `anyone` association carries only `read`.' }];
|
|
215
|
+
}
|
|
216
|
+
if (association.kind !== 'relationship')
|
|
201
217
|
return [];
|
|
202
218
|
return targetErrors(association.target, `${path}.target`);
|
|
203
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Who a duplicated permission names, since kind and label alone don't
|
|
222
|
+
* distinguish two grants of the same bit to different grantees.
|
|
223
|
+
*/
|
|
224
|
+
function granteeSuffix(association) {
|
|
225
|
+
if (association.kind !== 'permission')
|
|
226
|
+
return '';
|
|
227
|
+
const g = association.grantee;
|
|
228
|
+
return g.scope === 'entity' ? ` for "${g.entityId}"` : ` for ${g.role}s of "${g.groupId}"`;
|
|
229
|
+
}
|
|
230
|
+
/** The kinds an association may name — the closed set every surface reads. */
|
|
231
|
+
const ASSOCIATION_KINDS = new Set(['tag', 'attachment', 'relationship', 'permission', 'anyone']);
|
|
232
|
+
/**
|
|
233
|
+
* Whether a value is an association at all. Asked ahead of the partition
|
|
234
|
+
* checks, so a malformed element is named as one rather than reported as
|
|
235
|
+
* the wrong surface for a kind it never had — a request body supplies raw
|
|
236
|
+
* JSON, and `null` or `{}` is neither half of the partition.
|
|
237
|
+
*/
|
|
238
|
+
function namesKind(association) {
|
|
239
|
+
return (!!association &&
|
|
240
|
+
typeof association === 'object' &&
|
|
241
|
+
ASSOCIATION_KINDS.has(association.kind));
|
|
242
|
+
}
|
|
243
|
+
/** The bits a permission element may name — the whole of its meaning. */
|
|
244
|
+
const PERMISSION_LABELS = new Set(['read', 'write']);
|
|
245
|
+
/**
|
|
246
|
+
* Collect what makes a permission element malformed. `role` is required on
|
|
247
|
+
* a group grantee: there is no "any member" default to fall back on, so an
|
|
248
|
+
* absent one would otherwise widen or narrow silently depending on how the
|
|
249
|
+
* reader broke the tie. See docs/spec/access-control.md
|
|
250
|
+
* § Record-level permissions.
|
|
251
|
+
*/
|
|
252
|
+
function granteeErrors(association, path) {
|
|
253
|
+
const fail = (message) => [{ path, message }];
|
|
254
|
+
if (!PERMISSION_LABELS.has(association.label)) {
|
|
255
|
+
return [
|
|
256
|
+
{
|
|
257
|
+
path: `${path.slice(0, -'.grantee'.length)}.label`,
|
|
258
|
+
message: `Unknown permission label "${association.label}": expected "read" or "write".`,
|
|
259
|
+
},
|
|
260
|
+
];
|
|
261
|
+
}
|
|
262
|
+
const grantee = association.grantee;
|
|
263
|
+
if (!grantee || typeof grantee !== 'object')
|
|
264
|
+
return fail('A permission requires a grantee.');
|
|
265
|
+
if (grantee.scope === 'entity') {
|
|
266
|
+
return grantee.entityId ? [] : fail('An entity grantee requires a non-empty entityId.');
|
|
267
|
+
}
|
|
268
|
+
if (grantee.scope === 'group') {
|
|
269
|
+
if (!grantee.groupId)
|
|
270
|
+
return fail('A group grantee requires a non-empty groupId.');
|
|
271
|
+
return grantee.role === 'member' || grantee.role === 'admin'
|
|
272
|
+
? []
|
|
273
|
+
: fail('A group grantee requires a role of "member" or "admin".');
|
|
274
|
+
}
|
|
275
|
+
return fail(`Unknown permission grantee scope "${String(grantee.scope)}": expected "entity" or "group".`);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Refuse an authority element reaching the data half of the partition.
|
|
279
|
+
* The two share a table, a delta shape and a durability tier; they never
|
|
280
|
+
* share a call, because an app editing tags would otherwise be able to
|
|
281
|
+
* replace an ACL it was never shown. Thrown rather than collected: the
|
|
282
|
+
* caller named the wrong surface, not a malformed value, and the verb it
|
|
283
|
+
* wanted is `grantAccess()`/`revokeAccess()`.
|
|
284
|
+
*
|
|
285
|
+
* Lives here, in the invariant layer, so an unscoped `Stack`, an import
|
|
286
|
+
* and a server mapping a request body are all held to it.
|
|
287
|
+
* See docs/spec/access-control.md § Record-level permissions.
|
|
288
|
+
*/
|
|
289
|
+
export function assertDataAssociations(associations, surface) {
|
|
290
|
+
const authority = associations.find((a) => namesKind(a) && isAuthorityAssociation(a));
|
|
291
|
+
if (!authority)
|
|
292
|
+
return;
|
|
293
|
+
throw new StackQueryError(`${surface} does not carry authority: a "${authority.kind}" association belongs to the ` +
|
|
294
|
+
'`permissions` surface — use grantAccess()/revokeAccess(), or the `permissions` change-set key.');
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* The mirror of assertDataAssociations(): the `permissions` surface takes
|
|
298
|
+
* authority kinds alone, so a tag routed through it is refused rather than
|
|
299
|
+
* quietly becoming an ACL entry the `associations` projection never shows.
|
|
300
|
+
*/
|
|
301
|
+
export function assertAuthorityAssociations(permissions, surface) {
|
|
302
|
+
const data = permissions.find((a) => namesKind(a) && !isAuthorityAssociation(a));
|
|
303
|
+
if (!data)
|
|
304
|
+
return;
|
|
305
|
+
throw new StackQueryError(`${surface} carries authority alone: a "${data.kind}" association belongs to the ` +
|
|
306
|
+
'`associations` surface — use associate()/dissociate(), or the `associations` change-set key.');
|
|
307
|
+
}
|
|
204
308
|
/** validateAssociation() over a create's `associations` array. */
|
|
205
309
|
/**
|
|
206
310
|
* Every association in a list, plus the one rule a list has that a single
|
|
@@ -220,7 +324,7 @@ export function validateAssociations(associations, path = 'associations') {
|
|
|
220
324
|
? [
|
|
221
325
|
{
|
|
222
326
|
path: `${path}[${i}]`,
|
|
223
|
-
message: `Duplicate association identity: ${a.kind} "${a.label}" is named more than once.`,
|
|
327
|
+
message: `Duplicate association identity: ${a.kind} "${a.label}"${granteeSuffix(a)} is named more than once.`,
|
|
224
328
|
},
|
|
225
329
|
]
|
|
226
330
|
: []),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-validation.js","sourceRoot":"","sources":["../src/query-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"query-validation.js","sourceRoot":"","sources":["../src/query-validation.ts"],"names":[],"mappings":"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"}
|