@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.
Files changed (317) hide show
  1. package/README.md +124 -64
  2. package/dist/access.d.ts +43 -47
  3. package/dist/access.d.ts.map +1 -1
  4. package/dist/access.js +66 -101
  5. package/dist/access.js.map +1 -1
  6. package/dist/{combine.d.ts → adapter/combine.d.ts} +8 -1
  7. package/dist/adapter/combine.d.ts.map +1 -0
  8. package/dist/{combine.js → adapter/combine.js} +18 -3
  9. package/dist/adapter/combine.js.map +1 -0
  10. package/dist/adapter/index.d.ts +19 -0
  11. package/dist/adapter/index.d.ts.map +1 -0
  12. package/dist/adapter/index.js +16 -0
  13. package/dist/adapter/index.js.map +1 -0
  14. package/dist/adapter/reach.d.ts +14 -0
  15. package/dist/adapter/reach.d.ts.map +1 -0
  16. package/dist/adapter/reach.js +31 -0
  17. package/dist/adapter/reach.js.map +1 -0
  18. package/dist/{sort.d.ts → adapter/sort.d.ts} +20 -20
  19. package/dist/adapter/sort.d.ts.map +1 -0
  20. package/dist/{sort.js → adapter/sort.js} +37 -27
  21. package/dist/adapter/sort.js.map +1 -0
  22. package/dist/associations/identity.d.ts +69 -0
  23. package/dist/associations/identity.d.ts.map +1 -0
  24. package/dist/associations/identity.js +174 -0
  25. package/dist/associations/identity.js.map +1 -0
  26. package/dist/associations/validation.d.ts +83 -0
  27. package/dist/associations/validation.d.ts.map +1 -0
  28. package/dist/associations/validation.js +312 -0
  29. package/dist/associations/validation.js.map +1 -0
  30. package/dist/attachment-records.d.ts +48 -0
  31. package/dist/attachment-records.d.ts.map +1 -0
  32. package/dist/attachment-records.js +52 -0
  33. package/dist/attachment-records.js.map +1 -0
  34. package/dist/collection.d.ts +178 -0
  35. package/dist/collection.d.ts.map +1 -0
  36. package/dist/collection.js +397 -0
  37. package/dist/collection.js.map +1 -0
  38. package/dist/content-match.d.ts +25 -0
  39. package/dist/content-match.d.ts.map +1 -0
  40. package/dist/content-match.js +51 -0
  41. package/dist/content-match.js.map +1 -0
  42. package/dist/content-translation.d.ts +42 -0
  43. package/dist/content-translation.d.ts.map +1 -0
  44. package/dist/content-translation.js +108 -0
  45. package/dist/content-translation.js.map +1 -0
  46. package/dist/did/did.d.ts.map +1 -0
  47. package/dist/{did.js → did/did.js} +3 -4
  48. package/dist/did/did.js.map +1 -0
  49. package/dist/{did-entry.d.ts → did/index.d.ts} +1 -1
  50. package/dist/did/index.d.ts.map +1 -0
  51. package/dist/{did-entry.js → did/index.js} +3 -3
  52. package/dist/did/index.js.map +1 -0
  53. package/dist/errors.d.ts +54 -66
  54. package/dist/errors.d.ts.map +1 -1
  55. package/dist/errors.js +58 -62
  56. package/dist/errors.js.map +1 -1
  57. package/dist/grants.d.ts +20 -44
  58. package/dist/grants.d.ts.map +1 -1
  59. package/dist/grants.js +69 -151
  60. package/dist/grants.js.map +1 -1
  61. package/dist/id.d.ts +13 -31
  62. package/dist/id.d.ts.map +1 -1
  63. package/dist/id.js +13 -31
  64. package/dist/id.js.map +1 -1
  65. package/dist/index.d.ts +13 -9
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +9 -6
  68. package/dist/index.js.map +1 -1
  69. package/dist/install.d.ts +3 -6
  70. package/dist/install.d.ts.map +1 -1
  71. package/dist/install.js +6 -10
  72. package/dist/install.js.map +1 -1
  73. package/dist/lazy.d.ts +13 -0
  74. package/dist/lazy.d.ts.map +1 -0
  75. package/dist/lazy.js +27 -0
  76. package/dist/lazy.js.map +1 -0
  77. package/dist/merge.d.ts +1 -1
  78. package/dist/merge.d.ts.map +1 -1
  79. package/dist/merge.js +6 -12
  80. package/dist/merge.js.map +1 -1
  81. package/dist/migration-steps.d.ts +102 -0
  82. package/dist/migration-steps.d.ts.map +1 -0
  83. package/dist/migration-steps.js +293 -0
  84. package/dist/migration-steps.js.map +1 -0
  85. package/dist/query-validation.d.ts +68 -121
  86. package/dist/query-validation.d.ts.map +1 -1
  87. package/dist/query-validation.js +214 -380
  88. package/dist/query-validation.js.map +1 -1
  89. package/dist/record-changes.d.ts +11 -150
  90. package/dist/record-changes.d.ts.map +1 -1
  91. package/dist/record-changes.js +14 -305
  92. package/dist/record-changes.js.map +1 -1
  93. package/dist/schema.d.ts +18 -7
  94. package/dist/schema.d.ts.map +1 -1
  95. package/dist/schema.js +59 -30
  96. package/dist/schema.js.map +1 -1
  97. package/dist/scoped-stack/authority-snapshot.d.ts +37 -0
  98. package/dist/scoped-stack/authority-snapshot.d.ts.map +1 -0
  99. package/dist/scoped-stack/authority-snapshot.js +49 -0
  100. package/dist/scoped-stack/authority-snapshot.js.map +1 -0
  101. package/dist/scoped-stack/authority.d.ts +169 -0
  102. package/dist/scoped-stack/authority.d.ts.map +1 -0
  103. package/dist/scoped-stack/authority.js +408 -0
  104. package/dist/scoped-stack/authority.js.map +1 -0
  105. package/dist/scoped-stack/family-policy.d.ts +59 -0
  106. package/dist/scoped-stack/family-policy.d.ts.map +1 -0
  107. package/dist/scoped-stack/family-policy.js +68 -0
  108. package/dist/scoped-stack/family-policy.js.map +1 -0
  109. package/dist/scoped-stack/scoped-stack.d.ts +318 -0
  110. package/dist/scoped-stack/scoped-stack.d.ts.map +1 -0
  111. package/dist/scoped-stack/scoped-stack.js +695 -0
  112. package/dist/scoped-stack/scoped-stack.js.map +1 -0
  113. package/dist/scoped-stack/subscription.d.ts +36 -0
  114. package/dist/scoped-stack/subscription.d.ts.map +1 -0
  115. package/dist/scoped-stack/subscription.js +69 -0
  116. package/dist/scoped-stack/subscription.js.map +1 -0
  117. package/dist/stack/arguments.d.ts +27 -0
  118. package/dist/stack/arguments.d.ts.map +1 -0
  119. package/dist/stack/arguments.js +53 -0
  120. package/dist/stack/arguments.js.map +1 -0
  121. package/dist/stack/attachments.d.ts +24 -0
  122. package/dist/stack/attachments.d.ts.map +1 -0
  123. package/dist/stack/attachments.js +113 -0
  124. package/dist/stack/attachments.js.map +1 -0
  125. package/dist/{changes.d.ts → stack/changes.d.ts} +30 -72
  126. package/dist/stack/changes.d.ts.map +1 -0
  127. package/dist/{changes.js → stack/changes.js} +40 -74
  128. package/dist/stack/changes.js.map +1 -0
  129. package/dist/stack/client.d.ts +247 -0
  130. package/dist/stack/client.d.ts.map +1 -0
  131. package/dist/stack/client.js +9 -0
  132. package/dist/stack/client.js.map +1 -0
  133. package/dist/stack/identity-bindings.d.ts.map +1 -0
  134. package/dist/{identity-bindings.js → stack/identity-bindings.js} +5 -14
  135. package/dist/stack/identity-bindings.js.map +1 -0
  136. package/dist/stack/install-app.d.ts +22 -0
  137. package/dist/stack/install-app.d.ts.map +1 -0
  138. package/dist/stack/install-app.js +262 -0
  139. package/dist/stack/install-app.js.map +1 -0
  140. package/dist/stack/integrity.d.ts +94 -0
  141. package/dist/stack/integrity.d.ts.map +1 -0
  142. package/dist/stack/integrity.js +268 -0
  143. package/dist/stack/integrity.js.map +1 -0
  144. package/dist/{limits.d.ts → stack/limits.d.ts} +2 -5
  145. package/dist/stack/limits.d.ts.map +1 -0
  146. package/dist/{limits.js → stack/limits.js} +3 -6
  147. package/dist/stack/limits.js.map +1 -0
  148. package/dist/stack/migrations.d.ts +59 -0
  149. package/dist/stack/migrations.d.ts.map +1 -0
  150. package/dist/stack/migrations.js +141 -0
  151. package/dist/stack/migrations.js.map +1 -0
  152. package/dist/stack/reads.d.ts +69 -0
  153. package/dist/stack/reads.d.ts.map +1 -0
  154. package/dist/stack/reads.js +141 -0
  155. package/dist/stack/reads.js.map +1 -0
  156. package/dist/stack/record-id.d.ts +35 -0
  157. package/dist/stack/record-id.d.ts.map +1 -0
  158. package/dist/stack/record-id.js +82 -0
  159. package/dist/stack/record-id.js.map +1 -0
  160. package/dist/stack/stack.d.ts +444 -0
  161. package/dist/stack/stack.d.ts.map +1 -0
  162. package/dist/stack/stack.js +1339 -0
  163. package/dist/stack/stack.js.map +1 -0
  164. package/dist/stack/system-types.d.ts +16 -0
  165. package/dist/stack/system-types.d.ts.map +1 -0
  166. package/dist/stack/system-types.js +111 -0
  167. package/dist/stack/system-types.js.map +1 -0
  168. package/dist/stack/type-grants.d.ts +20 -0
  169. package/dist/stack/type-grants.d.ts.map +1 -0
  170. package/dist/stack/type-grants.js +69 -0
  171. package/dist/stack/type-grants.js.map +1 -0
  172. package/dist/stack/write-expectation.d.ts +79 -0
  173. package/dist/stack/write-expectation.d.ts.map +1 -0
  174. package/dist/stack/write-expectation.js +71 -0
  175. package/dist/stack/write-expectation.js.map +1 -0
  176. package/dist/stack/write-gate.d.ts +23 -0
  177. package/dist/stack/write-gate.d.ts.map +1 -0
  178. package/dist/stack/write-gate.js +17 -0
  179. package/dist/stack/write-gate.js.map +1 -0
  180. package/dist/testing.d.ts +44 -33
  181. package/dist/testing.d.ts.map +1 -1
  182. package/dist/testing.js +180 -176
  183. package/dist/testing.js.map +1 -1
  184. package/dist/type-handle.d.ts +67 -78
  185. package/dist/type-handle.d.ts.map +1 -1
  186. package/dist/type-handle.js +44 -111
  187. package/dist/type-handle.js.map +1 -1
  188. package/dist/types/adapter.d.ts +282 -0
  189. package/dist/types/adapter.d.ts.map +1 -0
  190. package/dist/types/adapter.js +5 -0
  191. package/dist/types/adapter.js.map +1 -0
  192. package/dist/types/associations.d.ts +140 -0
  193. package/dist/types/associations.d.ts.map +1 -0
  194. package/dist/types/associations.js +6 -0
  195. package/dist/types/associations.js.map +1 -0
  196. package/dist/types/capabilities.d.ts +89 -0
  197. package/dist/types/capabilities.d.ts.map +1 -0
  198. package/dist/types/capabilities.js +5 -0
  199. package/dist/types/capabilities.js.map +1 -0
  200. package/dist/types/events.d.ts +150 -0
  201. package/dist/types/events.d.ts.map +1 -0
  202. package/dist/types/events.js +5 -0
  203. package/dist/types/events.js.map +1 -0
  204. package/dist/types/ids.d.ts +43 -0
  205. package/dist/types/ids.d.ts.map +1 -0
  206. package/dist/types/ids.js +5 -0
  207. package/dist/types/ids.js.map +1 -0
  208. package/dist/types/index.d.ts +19 -0
  209. package/dist/types/index.d.ts.map +1 -0
  210. package/dist/types/index.js +19 -0
  211. package/dist/types/index.js.map +1 -0
  212. package/dist/types/journal.d.ts +47 -0
  213. package/dist/types/journal.d.ts.map +1 -0
  214. package/dist/types/journal.js +5 -0
  215. package/dist/types/journal.js.map +1 -0
  216. package/dist/types/query.d.ts +185 -0
  217. package/dist/types/query.d.ts.map +1 -0
  218. package/dist/types/query.js +10 -0
  219. package/dist/types/query.js.map +1 -0
  220. package/dist/types/records.d.ts +76 -0
  221. package/dist/types/records.d.ts.map +1 -0
  222. package/dist/types/records.js +5 -0
  223. package/dist/types/records.js.map +1 -0
  224. package/dist/types/schema.d.ts +74 -0
  225. package/dist/types/schema.d.ts.map +1 -0
  226. package/dist/types/schema.js +5 -0
  227. package/dist/types/schema.js.map +1 -0
  228. package/dist/types/system.d.ts +161 -0
  229. package/dist/types/system.d.ts.map +1 -0
  230. package/dist/types/system.js +32 -0
  231. package/dist/types/system.js.map +1 -0
  232. package/dist/types/tokens.d.ts +39 -0
  233. package/dist/types/tokens.d.ts.map +1 -0
  234. package/dist/types/tokens.js +5 -0
  235. package/dist/types/tokens.js.map +1 -0
  236. package/dist/validate.d.ts +31 -70
  237. package/dist/validate.d.ts.map +1 -1
  238. package/dist/validate.js +52 -92
  239. package/dist/validate.js.map +1 -1
  240. package/dist/{attachment-download.d.ts → wire/attachment-download.d.ts} +0 -57
  241. package/dist/wire/attachment-download.d.ts.map +1 -0
  242. package/dist/{attachment-download.js → wire/attachment-download.js} +0 -61
  243. package/dist/wire/attachment-download.js.map +1 -0
  244. package/dist/{auth.d.ts → wire/auth.d.ts} +5 -8
  245. package/dist/wire/auth.d.ts.map +1 -0
  246. package/dist/{auth.js → wire/auth.js} +5 -8
  247. package/dist/wire/auth.js.map +1 -0
  248. package/dist/{wire-body.d.ts → wire/body.d.ts} +35 -12
  249. package/dist/wire/body.d.ts.map +1 -0
  250. package/dist/{wire-body.js → wire/body.js} +74 -13
  251. package/dist/wire/body.js.map +1 -0
  252. package/dist/{wire-entry.d.ts → wire/index.d.ts} +12 -12
  253. package/dist/wire/index.d.ts.map +1 -0
  254. package/dist/{wire-entry.js → wire/index.js} +13 -17
  255. package/dist/wire/index.js.map +1 -0
  256. package/dist/wire/record.d.ts +31 -0
  257. package/dist/wire/record.d.ts.map +1 -0
  258. package/dist/{wire-record.js → wire/record.js} +7 -67
  259. package/dist/wire/record.js.map +1 -0
  260. package/dist/{wire-request.d.ts → wire/request.d.ts} +32 -49
  261. package/dist/wire/request.d.ts.map +1 -0
  262. package/dist/{wire-request.js → wire/request.js} +113 -83
  263. package/dist/wire/request.js.map +1 -0
  264. package/package.json +7 -7
  265. package/dist/adapter-entry.d.ts +0 -16
  266. package/dist/adapter-entry.d.ts.map +0 -1
  267. package/dist/adapter-entry.js +0 -14
  268. package/dist/adapter-entry.js.map +0 -1
  269. package/dist/attachment-download.d.ts.map +0 -1
  270. package/dist/attachment-download.js.map +0 -1
  271. package/dist/auth.d.ts.map +0 -1
  272. package/dist/auth.js.map +0 -1
  273. package/dist/changes.d.ts.map +0 -1
  274. package/dist/changes.js.map +0 -1
  275. package/dist/combine.d.ts.map +0 -1
  276. package/dist/combine.js.map +0 -1
  277. package/dist/did-entry.d.ts.map +0 -1
  278. package/dist/did-entry.js.map +0 -1
  279. package/dist/did.d.ts.map +0 -1
  280. package/dist/did.js.map +0 -1
  281. package/dist/identity-bindings.d.ts.map +0 -1
  282. package/dist/identity-bindings.js.map +0 -1
  283. package/dist/limits.d.ts.map +0 -1
  284. package/dist/limits.js.map +0 -1
  285. package/dist/record-id.d.ts +0 -70
  286. package/dist/record-id.d.ts.map +0 -1
  287. package/dist/record-id.js +0 -127
  288. package/dist/record-id.js.map +0 -1
  289. package/dist/scoped-stack.d.ts +0 -549
  290. package/dist/scoped-stack.d.ts.map +0 -1
  291. package/dist/scoped-stack.js +0 -1301
  292. package/dist/scoped-stack.js.map +0 -1
  293. package/dist/sort.d.ts.map +0 -1
  294. package/dist/sort.js.map +0 -1
  295. package/dist/stack-reads.d.ts +0 -38
  296. package/dist/stack-reads.d.ts.map +0 -1
  297. package/dist/stack-reads.js +0 -79
  298. package/dist/stack-reads.js.map +0 -1
  299. package/dist/stack.d.ts +0 -1032
  300. package/dist/stack.d.ts.map +0 -1
  301. package/dist/stack.js +0 -2337
  302. package/dist/stack.js.map +0 -1
  303. package/dist/types.d.ts +0 -1278
  304. package/dist/types.d.ts.map +0 -1
  305. package/dist/types.js +0 -51
  306. package/dist/types.js.map +0 -1
  307. package/dist/wire-body.d.ts.map +0 -1
  308. package/dist/wire-body.js.map +0 -1
  309. package/dist/wire-entry.d.ts.map +0 -1
  310. package/dist/wire-entry.js.map +0 -1
  311. package/dist/wire-record.d.ts +0 -50
  312. package/dist/wire-record.d.ts.map +0 -1
  313. package/dist/wire-record.js.map +0 -1
  314. package/dist/wire-request.d.ts.map +0 -1
  315. package/dist/wire-request.js.map +0 -1
  316. /package/dist/{did.d.ts → did/did.d.ts} +0 -0
  317. /package/dist/{identity-bindings.d.ts → stack/identity-bindings.d.ts} +0 -0
@@ -0,0 +1,408 @@
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 { groupRoleFromAssociations, isOwnerActingAlone, readCompanions, roleSatisfies, } from '../access.js';
12
+ import { inReach } from '../adapter/reach.js';
13
+ import { StackError, StackNotFoundError, StackPermissionError } from '../errors.js';
14
+ import { UNGRANTABLE_SYSTEM_TYPES, grantConveys, grantCoversGrantee, grantReach, } from '../grants.js';
15
+ import { filtersContent, splitQuery } from '../query-validation.js';
16
+ import { baseIdOf, fileRefFields } from '../schema.js';
17
+ import { familyPolicy } from './family-policy.js';
18
+ import { claimedFamilies, familyStanding, INSTALL_APP_LABEL, linkedIds } from '../install.js';
19
+ import { findFirstMatch, loadGrantRecords, loadInstallRecords, loadRosterRoles, queryAllPages, } from '../stack/reads.js';
20
+ import { AuthoritySnapshot } from './authority-snapshot.js';
21
+ import { SYSTEM_TYPES } from '../types/index.js';
22
+ /**
23
+ * How each side of a request reads a grant. The subject is the entity a
24
+ * grant is written about, so every tier counts; on the principal's side
25
+ * only a grant naming it directly counts. See
26
+ * docs/spec/access-control.md § Delegation: principal and subject.
27
+ */
28
+ const SUBJECT_SIDE = { allowDefault: true, allowGroup: true };
29
+ const PRINCIPAL_SIDE = { allowDefault: false, allowGroup: false };
30
+ /**
31
+ * What each verb is granted by: the grant action reaching a family whole,
32
+ * the one reaching the subject's own Records in it, and the permission bit
33
+ * reaching one Record. See docs/spec/access-control.md § Reach.
34
+ */
35
+ const VERBS = {
36
+ create: { any: 'create' },
37
+ read: { any: 'read-any', own: 'read-own', bit: 'read' },
38
+ update: { any: 'update-any', own: 'update-own', bit: 'write' },
39
+ delete: { any: 'delete-any', own: 'delete-own', bit: 'write' },
40
+ };
41
+ const ANYONE = { kind: 'anyone', label: 'read' };
42
+ export class ScopeAuthority {
43
+ stack;
44
+ principalId;
45
+ subjectId;
46
+ queryReadable;
47
+ constructor(stack,
48
+ /** Whose grants bound what this request may do — see ScopedStack.principalId. */
49
+ principalId,
50
+ /** Whom this request acts for and attributes writes to — see ScopedStack.subjectId. */
51
+ subjectId,
52
+ /** Stack.query() within a reach — see ScopedStack.query(). */
53
+ queryReadable) {
54
+ this.stack = stack;
55
+ this.principalId = principalId;
56
+ this.subjectId = subjectId;
57
+ this.queryReadable = queryReadable;
58
+ }
59
+ /**
60
+ * The authority this request acts with, for one operation: pass it to
61
+ * each check the operation makes, so the grants, the rosters and each
62
+ * verb's reach are read at most once. An anonymous request is named by no
63
+ * grant and held by no roster, so it reads neither.
64
+ */
65
+ snapshot() {
66
+ const subject = this.subjectId;
67
+ return new AuthoritySnapshot({
68
+ grants: () => this.identified ? loadGrantRecords((q) => this.stack.query(q)) : Promise.resolve([]),
69
+ roles: () => subject === null
70
+ ? Promise.resolve(new Map())
71
+ : loadRosterRoles((q) => this.stack.query(q), subject),
72
+ reach: (verb, snapshot) => this.buildReach(verb, snapshot),
73
+ });
74
+ }
75
+ /** Whether a delegated app is acting for someone other than itself. */
76
+ get delegated() {
77
+ return this.subjectId !== this.principalId;
78
+ }
79
+ /**
80
+ * Whether any grant could name this request — the one question every
81
+ * prefetch asks before scanning the `_grant` family, since an anonymous
82
+ * requester is reached by none. Both identities are read: `asEntity()`
83
+ * refuses an anonymous principal acting for a subject, so they are null
84
+ * together, and saying so costs nothing.
85
+ */
86
+ get identified() {
87
+ return this.principalId !== null || this.subjectId !== null;
88
+ }
89
+ /**
90
+ * Who this request is, for stamping onto whatever it mutates. Attribution
91
+ * follows record-level authorship: the subject is the actor, and the
92
+ * principal is named beside it only when the two differ.
93
+ * See docs/spec/data-model.md § Authorship and attribution.
94
+ */
95
+ get requester() {
96
+ if (this.subjectId === null)
97
+ return undefined;
98
+ return this.delegated && this.principalId !== null
99
+ ? { subjectId: this.subjectId, principalId: this.principalId }
100
+ : { subjectId: this.subjectId };
101
+ }
102
+ /**
103
+ * Whether unconditional owner authority applies — the owner acting as
104
+ * itself. The verbs resting on it are irreversible or disclose the sharing
105
+ * graph, so delegation never carries it, whichever side the owner is on.
106
+ * See docs/spec/access-control.md § Delegation: principal and subject.
107
+ */
108
+ get ownerActingAlone() {
109
+ return isOwnerActingAlone({ principalId: this.principalId, subjectId: this.subjectId }, this.stack.ownerEntityId);
110
+ }
111
+ /**
112
+ * Whether no grant bounds the principal: undelegated, it is the subject
113
+ * itself, and the owner as principal is the owner's own software.
114
+ * See docs/spec/access-control.md § Delegation: principal and subject.
115
+ */
116
+ get principalUnbounded() {
117
+ return !this.delegated || this.principalId === this.stack.ownerEntityId;
118
+ }
119
+ /**
120
+ * The families `grantee`'s grants convey one of `actions` on, read the way
121
+ * `side` reads a grant. Only the subject's side counts a group, so the
122
+ * rosters read are always the subject's.
123
+ * See docs/spec/access-control.md § Who a grant reaches.
124
+ */
125
+ async familiesConveying(grantee, side, actions, snapshot) {
126
+ if (!grantee)
127
+ return [];
128
+ const families = new Set();
129
+ for (const r of await snapshot.grants()) {
130
+ const c = r.content;
131
+ // A stored baseId is judged by grantReach(), which refuses a
132
+ // versioned one.
133
+ const reach = grantReach(c);
134
+ if (!reach || families.has(reach.familyId))
135
+ continue;
136
+ // grantType() refuses to write these, but a _grant record is an
137
+ // ordinary Record: an unscoped Stack, an import, or a server mapping
138
+ // a request body onto Stack can mint one anyway. Refusing at the
139
+ // point of use is what makes the rule hold regardless of how the
140
+ // record got there.
141
+ if (UNGRANTABLE_SYSTEM_TYPES.has(reach.familyId))
142
+ continue;
143
+ if (!actions.some((a) => grantConveys(reach.actions, a)))
144
+ continue;
145
+ if (await grantCoversGrantee(c, grantee, { ...side, roles: snapshot.roles })) {
146
+ families.add(reach.familyId);
147
+ }
148
+ }
149
+ return [...families];
150
+ }
151
+ /**
152
+ * What this request may do with `verb` — that verb's rules, built whole
153
+ * even where a Record's own permissions would settle it, since every gate
154
+ * asks one value at a flat cost. The principal's grants fence it; within,
155
+ * the subject reaches what grants and permissions give it, an owner
156
+ * subject everything. See docs/spec/access-control.md § Reach.
157
+ */
158
+ async buildReach(verb, snapshot) {
159
+ const { any, own, bit } = VERBS[verb];
160
+ const reach = this.principalUnbounded
161
+ ? {}
162
+ : {
163
+ fence: await this.familiesConveying(this.principalId, PRINCIPAL_SIDE, own ? [any, own] : [any], snapshot),
164
+ };
165
+ const subject = this.subjectId;
166
+ if (subject === this.stack.ownerEntityId)
167
+ return reach;
168
+ const families = (action) => this.familiesConveying(subject, SUBJECT_SIDE, [action], snapshot);
169
+ reach.within = {
170
+ baseIds: await families(any),
171
+ ...(subject !== null &&
172
+ own && { authored: { subjectId: subject, baseIds: await families(own) } }),
173
+ permissions: bit ? await this.elementSets(bit, snapshot) : [],
174
+ };
175
+ return reach;
176
+ }
177
+ /**
178
+ * The permission elements carrying `bit` to the subject, as the sets a
179
+ * Record must hold whole. A `read` stands alone, as does `anyone`; a
180
+ * `write` stands beside one of its readCompanions().
181
+ */
182
+ async elementSets(bit, snapshot) {
183
+ const grantees = [];
184
+ const subject = this.subjectId;
185
+ if (subject !== null) {
186
+ grantees.push({ kind: 'entity', entityId: subject });
187
+ for (const [groupId, held] of await snapshot.roles()) {
188
+ for (const role of ['member', 'admin']) {
189
+ if (roleSatisfies(held, role))
190
+ grantees.push({ kind: 'group', groupId, role });
191
+ }
192
+ }
193
+ }
194
+ const element = (label, grantee) => ({
195
+ kind: 'permission',
196
+ label,
197
+ grantee,
198
+ });
199
+ if (bit === 'read')
200
+ return [[ANYONE], ...grantees.map((g) => [element('read', g)])];
201
+ return grantees.flatMap((g) => readCompanions(g).map((c) => [element('write', g), c]));
202
+ }
203
+ /** Whether this request may `verb` the Record: its reach, asked of one Record. */
204
+ async may(verb, record, snapshot) {
205
+ return inReach(record, await snapshot.reach(verb));
206
+ }
207
+ /**
208
+ * may() with the principal's fence set aside — whether the subject alone
209
+ * reaches the Record, for a refusal that says which side lacked the verb.
210
+ */
211
+ async subjectMay(verb, record, snapshot) {
212
+ const { within } = await snapshot.reach(verb);
213
+ return inReach(record, within ? { within } : {});
214
+ }
215
+ canRead(record, snapshot) {
216
+ return this.may('read', record, snapshot);
217
+ }
218
+ /** Whether this request may create a Record of the type, asked of the Record it would make. */
219
+ canCreate(typeId, snapshot) {
220
+ return this.may('create', { typeId, createdBy: this.requester }, snapshot);
221
+ }
222
+ /**
223
+ * How to refuse a record this request addressed by ID: a permission error
224
+ * to a requester who can read it, the not-found answer to anyone else, so
225
+ * `message` only reaches someone holding the record already.
226
+ * See docs/spec/disclosure.md § Which refusal a Record answers with.
227
+ */
228
+ async denialFor(record, message, snapshot) {
229
+ if (await this.canRead(record, snapshot))
230
+ return new StackPermissionError(message);
231
+ return new StackNotFoundError(`Record not found: "${record.id}"`);
232
+ }
233
+ /**
234
+ * `_group` records are managed, not merely written: only the owner or an
235
+ * `admin` roster holder may mutate them — ordinary write permissions and
236
+ * grants don't apply. Asked of both identities under delegation, like
237
+ * a reshare. See docs/spec/identity.md § Group.
238
+ */
239
+ isGroupManager(record) {
240
+ if (!this.managesGroup(this.principalId, record))
241
+ return false;
242
+ return !this.delegated || this.managesGroup(this.subjectId, record);
243
+ }
244
+ /** Whether one identity, on its own, manages `record` — see isGroupManager(). */
245
+ managesGroup(entityId, record) {
246
+ if (!entityId)
247
+ return false;
248
+ if (entityId === this.stack.ownerEntityId)
249
+ return true;
250
+ return groupRoleFromAssociations(record.associations, entityId) === 'admin';
251
+ }
252
+ /**
253
+ * Whether this request may reference `recordId` as a parent or target.
254
+ * Missing and unreadable are both false, so this probes nothing. The
255
+ * owner acting alone skips the lookup and leaves absence to `Stack`.
256
+ * See docs/spec/access-control.md § Reference-creation gating.
257
+ */
258
+ async canReadReferent(recordId, snapshot) {
259
+ if (this.ownerActingAlone)
260
+ return true;
261
+ const record = await this.stack.get(recordId, { includeDeleted: true });
262
+ if (!record)
263
+ return false;
264
+ return this.canRead(record, snapshot);
265
+ }
266
+ /**
267
+ * Whether this request can read some record referencing `fileId`, other
268
+ * than an `_attachment@1` record — otherwise one correct guess would
269
+ * unlock unlimited further metadata records for the file.
270
+ * See docs/spec/attachments.md § Creating `_attachment@1` records directly.
271
+ */
272
+ async hasReadableReference(fileId, snapshot) {
273
+ const reach = await snapshot.reach('read');
274
+ const match = await findFirstMatch((q) => this.queryReadable(splitQuery(q), reach),
275
+ // Reach, not enumeration: a record readable by ID conveys the file it
276
+ // references. See docs/spec/unlisted.md.
277
+ { filter: { referencesFileId: fileId, includeUnlisted: true } }, (record) => baseIdOf(record.typeId) !== SYSTEM_TYPES.ATTACHMENT);
278
+ return match !== undefined;
279
+ }
280
+ /**
281
+ * Whether this request may reference or download `fileId` — the dual of
282
+ * getAttachment()'s access rule. Nonexistent and inaccessible are
283
+ * indistinguishable (both false), so no confirmation oracle for guessed
284
+ * hashes. See docs/spec/access-control.md § Reference-creation gating.
285
+ */
286
+ async canAccessFile(fileId, snapshot) {
287
+ if (this.ownerActingAlone)
288
+ return true;
289
+ // Reaching a file through a record this request can read is already
290
+ // fully intersected — the reach fences that record's own type, which
291
+ // is the type the reference lives on.
292
+ if (await this.hasReadableReference(fileId, snapshot))
293
+ return true;
294
+ if (!this.subjectId)
295
+ return false;
296
+ // The remaining paths are authorship facts about the subject, so they
297
+ // decide *which* files match — they are not themselves a grant, and the
298
+ // principal still needs one of its own on the attachment type.
299
+ const { fence } = await snapshot.reach('read');
300
+ if (fence && !fence.includes(SYSTEM_TYPES.ATTACHMENT))
301
+ return false;
302
+ if (this.subjectId === this.stack.ownerEntityId)
303
+ return true;
304
+ // `includeUnlisted`, as hasReadableReference() above: withholding a
305
+ // record from enumeration decides nothing about what it conveys, and
306
+ // the uploader clause does not lapse. See docs/spec/unlisted.md.
307
+ return filtersContent(this.stack.capabilities)
308
+ ? (await this.stack.query({
309
+ filter: {
310
+ typeId: `${SYSTEM_TYPES.ATTACHMENT}@1`,
311
+ createdBy: { subjectId: this.subjectId },
312
+ content: { fileId },
313
+ includeUnlisted: true,
314
+ },
315
+ limit: 1,
316
+ })).records.length > 0
317
+ : (await queryAllPages((q) => this.stack.query(q), {
318
+ filter: {
319
+ typeId: `${SYSTEM_TYPES.ATTACHMENT}@1`,
320
+ createdBy: { subjectId: this.subjectId },
321
+ includeUnlisted: true,
322
+ },
323
+ })).some((r) => r.content.fileId === fileId);
324
+ }
325
+ /**
326
+ * Whether this request is an installed app, acting as itself, migrating
327
+ * `record` within families its one live install claims, to a version the
328
+ * owner approved, holding `update-any` on each directly.
329
+ * See docs/spec/apps.md § Migrating an installed app's types.
330
+ */
331
+ async installMayMigrate(record, toTypeId, snapshot) {
332
+ const principal = this.principalId;
333
+ if (!principal || this.delegated)
334
+ return false;
335
+ const families = new Set([baseIdOf(record.typeId), baseIdOf(toTypeId)]);
336
+ const installs = await loadInstallRecords(this.stack);
337
+ let install;
338
+ for (const family of families) {
339
+ const claimants = installs.filter((r) => claimedFamilies(r.content).has(family));
340
+ if (claimants.length !== 1)
341
+ return false;
342
+ if (familyStanding(family, claimants[0].content.appId) !== 'own')
343
+ return false;
344
+ if (install && install.id !== claimants[0].id)
345
+ return false;
346
+ install = claimants[0];
347
+ }
348
+ if (!install || install.deletedAt)
349
+ return false;
350
+ if (!Array.isArray(install.content.defines) || !install.content.defines.includes(toTypeId)) {
351
+ return false;
352
+ }
353
+ let linked = false;
354
+ for (const cardId of linkedIds(install, INSTALL_APP_LABEL)) {
355
+ const card = await this.stack.get(cardId);
356
+ if (card && baseIdOf(card.typeId) === SYSTEM_TYPES.APP) {
357
+ if (card.content.did === principal)
358
+ linked = true;
359
+ }
360
+ }
361
+ if (!linked)
362
+ return false;
363
+ // Grants naming the app itself: an install reaches only families the
364
+ // owner named it to, whoever else holds them.
365
+ const held = await this.familiesConveying(principal, PRINCIPAL_SIDE, ['update-any'], snapshot);
366
+ return [...families].every((family) => held.includes(family));
367
+ }
368
+ /** Names of the type's top-level file-ref fields — the content-reference half of referencesFileId matching. */
369
+ async fileRefFieldNames(typeId) {
370
+ const type = await this.stack.getType(typeId);
371
+ return type ? fileRefFields(type.schema) : [];
372
+ }
373
+ /**
374
+ * Whether this request may widen who reaches a record, at create time or
375
+ * after. A delegated app may not, unless the owner is its principal:
376
+ * widening access is what containment most needs to hold.
377
+ * See docs/spec/access-control.md § Delegation: principal and subject.
378
+ */
379
+ mayGrantAccess() {
380
+ return this.principalUnbounded;
381
+ }
382
+ /**
383
+ * Whether one identity, on its own, may decide who else reaches `record`
384
+ * — the owner-or-creator rule a reshare enforces, asked of one
385
+ * side at a time. See
386
+ * docs/spec/access-control.md § Delegation: principal and subject.
387
+ */
388
+ mayReshare(entityId, record) {
389
+ if (!entityId)
390
+ return false;
391
+ return entityId === this.stack.ownerEntityId || entityId === record.createdBy?.subjectId;
392
+ }
393
+ /**
394
+ * Whether this request may decide who else reaches `record`: management
395
+ * for a `_group`, so a demoted creator keeps no side door; otherwise the
396
+ * owner-or-author rule, asked of both sides of a delegation.
397
+ * See docs/spec/access-control.md § Record-level permissions.
398
+ */
399
+ canReshare(record) {
400
+ if (familyPolicy(record.typeId).writers === 'group-managers') {
401
+ return this.isGroupManager(record);
402
+ }
403
+ if (!this.mayReshare(this.principalId, record))
404
+ return false;
405
+ return !this.delegated || this.mayReshare(this.subjectId, record);
406
+ }
407
+ }
408
+ //# sourceMappingURL=authority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authority.js","sourceRoot":"","sources":["../../src/scoped-stack/authority.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * System family policies
3
+ * -------------------------------------------------------
4
+ * The rules a system family holds a scoped writer to on top of the
5
+ * ordinary gates: who may write its Records at all, which content values
6
+ * are the owner's alone to set, and what a create must already be able to
7
+ * reach. One entry per family, read by every verb through the questions
8
+ * below, so a rule reaches each verb that writes what it governs — create,
9
+ * patchContent(), restoreVersion() and commitMigration() alike — rather
10
+ * than only the ones that remembered to ask it.
11
+ *
12
+ * A family with no entry is ordinary. Grants on a family are refused
13
+ * separately, at the write and at evaluation (UNGRANTABLE_SYSTEM_TYPES in
14
+ * grants.ts), since a grant is not a scoped write.
15
+ *
16
+ * See docs/spec/access-control.md § Per-verb gates.
17
+ */
18
+ import type { EntityId, TypeId } from '../types/index.js';
19
+ /**
20
+ * Who may write a Record of a family, whatever its own `permissions` and
21
+ * any grant say: anyone the ordinary write gate admits, the owner acting
22
+ * alone, or the Group's admins and the owner.
23
+ */
24
+ export type FamilyWriters = 'ordinary' | 'owner-alone' | 'group-managers';
25
+ type FamilyPolicy = {
26
+ writers: FamilyWriters;
27
+ /**
28
+ * Content fields only the owner acting alone may set, and when: `any`
29
+ * change, or only a value naming the owner's own DID.
30
+ */
31
+ ownerFields?: {
32
+ fields: readonly string[];
33
+ when: 'any' | 'owner-did';
34
+ message: string;
35
+ };
36
+ /**
37
+ * A content field naming a file a non-owner create must already be able
38
+ * to read through some other Record — see docs/spec/attachments.md
39
+ * § Creating `_attachment@1` records directly.
40
+ */
41
+ createNamesFile?: string;
42
+ /**
43
+ * Whether `relationship` associations are a roster naming Entities
44
+ * rather than references to readable Records, and so carry no
45
+ * reference gate — see docs/spec/access-control.md § Reference-creation gating.
46
+ */
47
+ rosterAssociations?: boolean;
48
+ };
49
+ /** The policy a Record of `typeId` is held to. */
50
+ export declare const familyPolicy: (typeId: TypeId) => FamilyPolicy;
51
+ /**
52
+ * The refusal a write owes when it moves content only the owner acting
53
+ * alone may set, or null when it moves none. Compared value-wise between
54
+ * `before` (absent at create) and `after`, so re-sending a value a Record
55
+ * already holds claims nothing.
56
+ */
57
+ export declare const ownerFieldRefusal: (typeId: TypeId, before: Record<string, unknown> | undefined, after: Record<string, unknown>, ownerEntityId: EntityId) => string | null;
58
+ export {};
59
+ //# sourceMappingURL=family-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"family-policy.d.ts","sourceRoot":"","sources":["../../src/scoped-stack/family-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAE1E,KAAK,YAAY,GAAG;IAClB,OAAO,EAAE,aAAa,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE;QAAE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACxF;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAoCF,kDAAkD;AAClD,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,KAAG,YACF,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,MAAM,EACd,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,eAAe,QAAQ,KACtB,MAAM,GAAG,IAQX,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * System family policies
3
+ * -------------------------------------------------------
4
+ * The rules a system family holds a scoped writer to on top of the
5
+ * ordinary gates: who may write its Records at all, which content values
6
+ * are the owner's alone to set, and what a create must already be able to
7
+ * reach. One entry per family, read by every verb through the questions
8
+ * below, so a rule reaches each verb that writes what it governs — create,
9
+ * patchContent(), restoreVersion() and commitMigration() alike — rather
10
+ * than only the ones that remembered to ask it.
11
+ *
12
+ * A family with no entry is ordinary. Grants on a family are refused
13
+ * separately, at the write and at evaluation (UNGRANTABLE_SYSTEM_TYPES in
14
+ * grants.ts), since a grant is not a scoped write.
15
+ *
16
+ * See docs/spec/access-control.md § Per-verb gates.
17
+ */
18
+ import { baseIdOf } from '../schema.js';
19
+ import { bindingFieldsOf } from '../stack/identity-bindings.js';
20
+ import { SYSTEM_TYPES } from '../types/index.js';
21
+ const ORDINARY = { writers: 'ordinary' };
22
+ const POLICIES = new Map([
23
+ // Authority itself: see docs/spec/access-control.md § What a grant covers.
24
+ [SYSTEM_TYPES.GRANT, { writers: 'owner-alone' }],
25
+ [SYSTEM_TYPES.INSTALL, { writers: 'owner-alone' }],
26
+ // Managed, not merely written: see docs/spec/identity.md § Group.
27
+ [SYSTEM_TYPES.GROUP, { writers: 'group-managers', rosterAssociations: true }],
28
+ // See docs/spec/identity.md § DID bindings.
29
+ [
30
+ SYSTEM_TYPES.APP,
31
+ {
32
+ writers: 'ordinary',
33
+ ownerFields: {
34
+ fields: bindingFieldsOf(SYSTEM_TYPES.APP),
35
+ when: 'any',
36
+ message: 'Only the stack owner may set an _app record’s did or appId',
37
+ },
38
+ },
39
+ ],
40
+ [
41
+ SYSTEM_TYPES.ENTITY,
42
+ {
43
+ writers: 'ordinary',
44
+ ownerFields: {
45
+ fields: ['did'],
46
+ when: 'owner-did',
47
+ message: 'Only the stack owner may claim the owner’s own did',
48
+ },
49
+ },
50
+ ],
51
+ [SYSTEM_TYPES.ATTACHMENT, { writers: 'ordinary', createNamesFile: 'fileId' }],
52
+ ]);
53
+ /** The policy a Record of `typeId` is held to. */
54
+ export const familyPolicy = (typeId) => POLICIES.get(baseIdOf(typeId)) ?? ORDINARY;
55
+ /**
56
+ * The refusal a write owes when it moves content only the owner acting
57
+ * alone may set, or null when it moves none. Compared value-wise between
58
+ * `before` (absent at create) and `after`, so re-sending a value a Record
59
+ * already holds claims nothing.
60
+ */
61
+ export const ownerFieldRefusal = (typeId, before, after, ownerEntityId) => {
62
+ const rule = familyPolicy(typeId).ownerFields;
63
+ if (!rule)
64
+ return null;
65
+ const moved = rule.fields.some((field) => after[field] !== before?.[field] && (rule.when === 'any' || after[field] === ownerEntityId));
66
+ return moved ? rule.message : null;
67
+ };
68
+ //# sourceMappingURL=family-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"family-policy.js","sourceRoot":"","sources":["../../src/scoped-stack/family-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA+BjD,MAAM,QAAQ,GAAiB,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AAEvD,MAAM,QAAQ,GAAsC,IAAI,GAAG,CAAuB;IAChF,2EAA2E;IAC3E,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAChD,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAClD,kEAAkE;IAClE,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAC7E,4CAA4C;IAC5C;QACE,YAAY,CAAC,GAAG;QAChB;YACE,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE;gBACX,MAAM,EAAE,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC;gBACzC,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,4DAA4D;aACtE;SACF;KACF;IACD;QACE,YAAY,CAAC,MAAM;QACnB;YACE,OAAO,EAAE,UAAU;YACnB,WAAW,EAAE;gBACX,MAAM,EAAE,CAAC,KAAK,CAAC;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,oDAAoD;aAC9D;SACF;KACF;IACD,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC;CAC9E,CAAC,CAAC;AAEH,kDAAkD;AAClD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAc,EAAgB,EAAE,CAC3D,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,QAAQ,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,MAAc,EACd,MAA2C,EAC3C,KAA8B,EAC9B,aAAuB,EACR,EAAE;IACjB,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC;IAC9C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAC5B,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,aAAa,CAAC,CAC9F,CAAC;IACF,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACrC,CAAC,CAAC"}