@sixb/core 0.1.19 → 0.1.20

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 (211) hide show
  1. package/dist/actions/index.js +24 -24
  2. package/dist/agents/index.js +25 -25
  3. package/dist/agents/index.js.map +1 -1
  4. package/dist/auth/cookies.d.ts +2 -4
  5. package/dist/auth/cookies.d.ts.map +1 -1
  6. package/dist/auth/index.d.ts +0 -2
  7. package/dist/auth/index.d.ts.map +1 -1
  8. package/dist/auth/index.js +8 -14
  9. package/dist/auth/index.js.map +1 -1
  10. package/dist/auth/runtime.d.ts +8 -10
  11. package/dist/auth/runtime.d.ts.map +1 -1
  12. package/dist/auth/session-cache.d.ts +1 -5
  13. package/dist/auth/session-cache.d.ts.map +1 -1
  14. package/dist/auth/strategy.js +1 -1
  15. package/dist/auth/types.d.ts +4 -8
  16. package/dist/auth/types.d.ts.map +1 -1
  17. package/dist/auth/validation.d.ts +0 -1
  18. package/dist/auth/validation.d.ts.map +1 -1
  19. package/dist/authorization/decision.d.ts +0 -4
  20. package/dist/authorization/decision.d.ts.map +1 -1
  21. package/dist/authorization/grant-kinds.d.ts +6 -8
  22. package/dist/authorization/grant-kinds.d.ts.map +1 -1
  23. package/dist/authorization/index.d.ts +0 -1
  24. package/dist/authorization/index.d.ts.map +1 -1
  25. package/dist/authorization/index.js +3 -7
  26. package/dist/authorization/index.js.map +1 -1
  27. package/dist/authorization/resolve.d.ts +1 -1
  28. package/dist/authorization/resolve.d.ts.map +1 -1
  29. package/dist/bootstrap/index.js +26 -26
  30. package/dist/{chunk-aff7cyea.js → chunk-0rbyz4qy.js} +21 -21
  31. package/dist/{chunk-aff7cyea.js.map → chunk-0rbyz4qy.js.map} +1 -1
  32. package/dist/{chunk-rz53yb4v.js → chunk-0yh890a4.js} +1 -1
  33. package/dist/{chunk-7mbzgd9m.js → chunk-1zq2p6g0.js} +1 -1
  34. package/dist/{chunk-dnmadg9k.js → chunk-3t2hgbgd.js} +2 -2
  35. package/dist/{chunk-wwdfe68s.js → chunk-4vyr1j8f.js} +2 -2
  36. package/dist/{chunk-kyzq4wy9.js → chunk-5j58wjct.js} +15 -15
  37. package/dist/chunk-5j58wjct.js.map +18 -0
  38. package/dist/{chunk-ey3pyej1.js → chunk-6c6sn0bh.js} +29 -24
  39. package/dist/{chunk-ey3pyej1.js.map → chunk-6c6sn0bh.js.map} +3 -3
  40. package/dist/{chunk-q1vkr2ys.js → chunk-6p49a5cq.js} +2 -2
  41. package/dist/{chunk-nre82s12.js → chunk-9dmt152s.js} +1 -1
  42. package/dist/{chunk-7kg3k1m9.js → chunk-9w055r5b.js} +1 -1
  43. package/dist/{chunk-4tcx876c.js → chunk-bx9q3cwv.js} +15 -15
  44. package/dist/{chunk-4tcx876c.js.map → chunk-bx9q3cwv.js.map} +1 -1
  45. package/dist/{chunk-bpgy64fw.js → chunk-d09tj99x.js} +1 -1
  46. package/dist/{chunk-y7rqfrgg.js → chunk-d0bqz29d.js} +23 -36
  47. package/dist/chunk-d0bqz29d.js.map +23 -0
  48. package/dist/{chunk-rhg02hxq.js → chunk-dk8tkk5f.js} +3 -3
  49. package/dist/{chunk-xt1zt7gv.js → chunk-es1gxsbf.js} +24 -15
  50. package/dist/chunk-es1gxsbf.js.map +13 -0
  51. package/dist/{chunk-52bk93x8.js → chunk-fkgc1wt8.js} +1 -1
  52. package/dist/{chunk-enpsx8k5.js → chunk-gsjm1wms.js} +16 -20
  53. package/dist/chunk-gsjm1wms.js.map +10 -0
  54. package/dist/{chunk-2jntasmh.js → chunk-hcbyfxbe.js} +25 -49
  55. package/dist/chunk-hcbyfxbe.js.map +12 -0
  56. package/dist/{chunk-zrmy8zvw.js → chunk-hjzdd750.js} +3 -3
  57. package/dist/chunk-hkc3jct7.js.map +1 -1
  58. package/dist/{chunk-85yvv5n0.js → chunk-k6q3n2sc.js} +3 -3
  59. package/dist/{chunk-j2bp5ryw.js → chunk-n33z5bjw.js} +11 -10
  60. package/dist/{chunk-j2bp5ryw.js.map → chunk-n33z5bjw.js.map} +3 -3
  61. package/dist/{chunk-80mc0971.js → chunk-ren4kg2j.js} +8 -8
  62. package/dist/{chunk-1f7wpmyp.js → chunk-rrzt8jdy.js} +2 -2
  63. package/dist/{chunk-6gmfggss.js → chunk-t7x8dmn0.js} +2 -2
  64. package/dist/{chunk-wz0xs816.js → chunk-tg2cw67r.js} +1 -1
  65. package/dist/{chunk-3gnrh4ve.js → chunk-vpq4shxz.js} +46 -106
  66. package/dist/chunk-vpq4shxz.js.map +39 -0
  67. package/dist/{chunk-bwjcehza.js → chunk-way52z4h.js} +1 -1
  68. package/dist/{chunk-tjb1mk5t.js → chunk-x6m907x7.js} +2 -2
  69. package/dist/{chunk-t6vq7bff.js → chunk-xfs8x8m9.js} +3 -3
  70. package/dist/{chunk-d2ync1v3.js → chunk-yevzdx4y.js} +3 -3
  71. package/dist/{chunk-kg5j6fct.js → chunk-z4m0yz8c.js} +1 -1
  72. package/dist/datasets/write.js +5 -5
  73. package/dist/deploy/internal.js +4 -3
  74. package/dist/deploy/internal.js.map +4 -4
  75. package/dist/deploy/services.d.ts.map +1 -1
  76. package/dist/deploy/types.d.ts +1 -2
  77. package/dist/deploy/types.d.ts.map +1 -1
  78. package/dist/execution/agent.js +24 -24
  79. package/dist/execution/authorization.d.ts.map +1 -1
  80. package/dist/execution/primitive.js +24 -24
  81. package/dist/execution/request.js +23 -23
  82. package/dist/index.d.ts +5 -5
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +33 -46
  85. package/dist/index.js.map +1 -1
  86. package/dist/lake-storage/index.js +5 -5
  87. package/dist/materializer/index.js +13 -13
  88. package/dist/models/execution/index.js +10 -10
  89. package/dist/objects/index.js +24 -24
  90. package/dist/objects/query/index.js +12 -12
  91. package/dist/objects/vectors/handle.d.ts.map +1 -1
  92. package/dist/objects/vectors/profile.d.ts +5 -0
  93. package/dist/objects/vectors/profile.d.ts.map +1 -1
  94. package/dist/ontology/index.js +3 -3
  95. package/dist/pipelines/index.js +15 -15
  96. package/dist/projections/internal.js +13 -13
  97. package/dist/runtime/internal.js +13 -13
  98. package/dist/security/builders.d.ts.map +1 -1
  99. package/dist/security/every.d.ts +1 -4
  100. package/dist/security/every.d.ts.map +1 -1
  101. package/dist/security/grants.d.ts +2 -4
  102. package/dist/security/grants.d.ts.map +1 -1
  103. package/dist/security/index.d.ts +1 -2
  104. package/dist/security/index.d.ts.map +1 -1
  105. package/dist/security/membership-policies.d.ts.map +1 -1
  106. package/dist/security/public.d.ts +10 -0
  107. package/dist/security/public.d.ts.map +1 -0
  108. package/dist/security/public.js +10 -0
  109. package/dist/security/public.js.map +9 -0
  110. package/dist/security/registry.d.ts +0 -1
  111. package/dist/security/registry.d.ts.map +1 -1
  112. package/dist/security/types.d.ts +13 -18
  113. package/dist/security/types.d.ts.map +1 -1
  114. package/dist/security/validation.d.ts +0 -6
  115. package/dist/security/validation.d.ts.map +1 -1
  116. package/dist/shares/internal.js +10 -10
  117. package/dist/storage/agents/types.d.ts +1 -1
  118. package/dist/storage/auth/in-memory/auth-storage.d.ts.map +1 -1
  119. package/dist/storage/auth/in-memory/magic-links.d.ts.map +1 -1
  120. package/dist/storage/auth/in-memory/oidc-attempts.d.ts.map +1 -1
  121. package/dist/storage/auth/in-memory/sessions.d.ts +0 -10
  122. package/dist/storage/auth/in-memory/sessions.d.ts.map +1 -1
  123. package/dist/storage/auth/in-memory/shared.d.ts +1 -2
  124. package/dist/storage/auth/in-memory/shared.d.ts.map +1 -1
  125. package/dist/storage/auth/types.d.ts +1 -17
  126. package/dist/storage/auth/types.d.ts.map +1 -1
  127. package/dist/storage/file-upload-sessions/provider.js +6 -6
  128. package/dist/storage/index.js +21 -21
  129. package/dist/storage/index.js.map +1 -1
  130. package/dist/storage/workflow-runs/provider.js +6 -6
  131. package/dist/syncs/index.js +16 -16
  132. package/dist/testing/auth-storage-contract.d.ts.map +1 -1
  133. package/dist/testing/index.js +41 -124
  134. package/dist/testing/index.js.map +4 -4
  135. package/dist/webhooks/internal.js +11 -11
  136. package/dist/workflows/index.js +25 -25
  137. package/package.json +8 -2
  138. package/src/auth/cookies.ts +3 -20
  139. package/src/auth/index.ts +0 -6
  140. package/src/auth/runtime.ts +59 -76
  141. package/src/auth/session-cache.ts +2 -9
  142. package/src/auth/types.ts +4 -8
  143. package/src/auth/validation.ts +0 -2
  144. package/src/authorization/decision.ts +8 -23
  145. package/src/authorization/grant-kinds.ts +20 -27
  146. package/src/authorization/index.ts +0 -1
  147. package/src/authorization/resolve.ts +10 -6
  148. package/src/deploy/services.ts +0 -1
  149. package/src/deploy/types.ts +1 -2
  150. package/src/deploy/validation.ts +3 -1
  151. package/src/execution/authorization.ts +11 -5
  152. package/src/index.ts +1 -14
  153. package/src/models/execution/embedding.ts +6 -6
  154. package/src/objects/vectors/README.md +4 -0
  155. package/src/objects/vectors/handle.ts +11 -2
  156. package/src/objects/vectors/indexing-generate.ts +2 -2
  157. package/src/objects/vectors/profile.ts +5 -0
  158. package/src/security/builders.ts +7 -2
  159. package/src/security/every.ts +0 -4
  160. package/src/security/grants.ts +5 -25
  161. package/src/security/index.ts +0 -3
  162. package/src/security/membership-policies.ts +3 -1
  163. package/src/security/public.ts +10 -0
  164. package/src/security/registry.ts +0 -8
  165. package/src/security/types.ts +19 -25
  166. package/src/security/validation.ts +19 -17
  167. package/src/storage/agents/types.ts +1 -1
  168. package/src/storage/auth/in-memory/auth-storage.ts +0 -18
  169. package/src/storage/auth/in-memory/magic-links.ts +0 -3
  170. package/src/storage/auth/in-memory/oidc-attempts.ts +0 -3
  171. package/src/storage/auth/in-memory/sessions.ts +1 -25
  172. package/src/storage/auth/in-memory/shared.ts +1 -10
  173. package/src/storage/auth/types.ts +2 -18
  174. package/src/testing/auth-storage-contract.ts +14 -107
  175. package/src/testing/execution-storage-contract.ts +0 -2
  176. package/dist/auth/audience.d.ts +0 -8
  177. package/dist/auth/audience.d.ts.map +0 -1
  178. package/dist/authorization/application-access.d.ts +0 -18
  179. package/dist/authorization/application-access.d.ts.map +0 -1
  180. package/dist/chunk-2jntasmh.js.map +0 -13
  181. package/dist/chunk-3gnrh4ve.js.map +0 -40
  182. package/dist/chunk-enpsx8k5.js.map +0 -10
  183. package/dist/chunk-kyzq4wy9.js.map +0 -18
  184. package/dist/chunk-xt1zt7gv.js.map +0 -13
  185. package/dist/chunk-y7rqfrgg.js.map +0 -24
  186. package/dist/security/applications.d.ts +0 -15
  187. package/dist/security/applications.d.ts.map +0 -1
  188. package/src/auth/audience.ts +0 -28
  189. package/src/authorization/application-access.ts +0 -34
  190. package/src/security/applications.ts +0 -11
  191. /package/dist/{chunk-rz53yb4v.js.map → chunk-0yh890a4.js.map} +0 -0
  192. /package/dist/{chunk-7mbzgd9m.js.map → chunk-1zq2p6g0.js.map} +0 -0
  193. /package/dist/{chunk-dnmadg9k.js.map → chunk-3t2hgbgd.js.map} +0 -0
  194. /package/dist/{chunk-wwdfe68s.js.map → chunk-4vyr1j8f.js.map} +0 -0
  195. /package/dist/{chunk-q1vkr2ys.js.map → chunk-6p49a5cq.js.map} +0 -0
  196. /package/dist/{chunk-nre82s12.js.map → chunk-9dmt152s.js.map} +0 -0
  197. /package/dist/{chunk-7kg3k1m9.js.map → chunk-9w055r5b.js.map} +0 -0
  198. /package/dist/{chunk-bpgy64fw.js.map → chunk-d09tj99x.js.map} +0 -0
  199. /package/dist/{chunk-rhg02hxq.js.map → chunk-dk8tkk5f.js.map} +0 -0
  200. /package/dist/{chunk-52bk93x8.js.map → chunk-fkgc1wt8.js.map} +0 -0
  201. /package/dist/{chunk-zrmy8zvw.js.map → chunk-hjzdd750.js.map} +0 -0
  202. /package/dist/{chunk-85yvv5n0.js.map → chunk-k6q3n2sc.js.map} +0 -0
  203. /package/dist/{chunk-80mc0971.js.map → chunk-ren4kg2j.js.map} +0 -0
  204. /package/dist/{chunk-1f7wpmyp.js.map → chunk-rrzt8jdy.js.map} +0 -0
  205. /package/dist/{chunk-6gmfggss.js.map → chunk-t7x8dmn0.js.map} +0 -0
  206. /package/dist/{chunk-wz0xs816.js.map → chunk-tg2cw67r.js.map} +0 -0
  207. /package/dist/{chunk-bwjcehza.js.map → chunk-way52z4h.js.map} +0 -0
  208. /package/dist/{chunk-tjb1mk5t.js.map → chunk-x6m907x7.js.map} +0 -0
  209. /package/dist/{chunk-t6vq7bff.js.map → chunk-xfs8x8m9.js.map} +0 -0
  210. /package/dist/{chunk-d2ync1v3.js.map → chunk-yevzdx4y.js.map} +0 -0
  211. /package/dist/{chunk-kg5j6fct.js.map → chunk-z4m0yz8c.js.map} +0 -0
package/src/auth/types.ts CHANGED
@@ -11,7 +11,6 @@ import type {
11
11
  SessionRecord,
12
12
  UserRecord,
13
13
  } from "../storage/auth"
14
- import type { AuthSessionAudience, AuthSessionAudienceOptions } from "./audience"
15
14
 
16
15
  export type Principal =
17
16
  | { readonly type: "user"; readonly id: string }
@@ -63,7 +62,6 @@ export interface InvitationDeliveryInput {
63
62
  readonly projectId: string
64
63
  readonly authStorage: AuthStorage
65
64
  readonly invitation: InvitationRecord
66
- readonly audience: AuthSessionAudience
67
65
  readonly returnTo: string
68
66
  readonly requestOrigin: string
69
67
  /** Return the delivered link once so the inviter can copy it through an approved channel. */
@@ -98,7 +96,6 @@ export interface MagicLinkRequestInput {
98
96
  readonly projectId: string
99
97
  readonly authStorage: AuthStorage
100
98
  readonly email: string
101
- readonly audience: AuthSessionAudience
102
99
  readonly returnTo: string
103
100
  readonly requestOrigin: string
104
101
  /**
@@ -140,7 +137,6 @@ export interface MagicLinkCallbackInput {
140
137
  }
141
138
 
142
139
  export interface MagicLinkCallbackResult extends CompleteSignInResult {
143
- readonly audience: AuthSessionAudience
144
140
  readonly returnTo: string
145
141
  }
146
142
 
@@ -182,7 +178,6 @@ export interface MagicLinkAuthStrategy extends InvitationDeliveryAuthStrategy {
182
178
  export interface OidcStartSignInInput {
183
179
  readonly projectId: string
184
180
  readonly authStorage: AuthStorage
185
- readonly audience: AuthSessionAudience
186
181
  readonly returnTo: string
187
182
  readonly requestOrigin: string
188
183
  readonly now?: Date
@@ -208,7 +203,6 @@ export interface OidcCallbackInput {
208
203
  }
209
204
 
210
205
  export interface OidcCallbackResult extends CompleteSignInResult {
211
- readonly audience: AuthSessionAudience
212
206
  readonly returnTo: string
213
207
  }
214
208
 
@@ -277,11 +271,14 @@ export interface MembershipOperationCapabilities {
277
271
  readonly invite: boolean
278
272
  readonly assignGroups: boolean
279
273
  readonly suspend: boolean
274
+ readonly serviceAccounts: boolean
280
275
  }
281
276
 
282
277
  export interface GetMembershipOptionsResult {
283
278
  /** Groups the caller may assign to a member (the `assignGroups` scope). */
284
279
  readonly groups: readonly InvitationGroupOption[]
280
+ /** Groups the caller may place a service account in (the `serviceAccounts` scope). */
281
+ readonly serviceAccountGroups: readonly InvitationGroupOption[]
285
282
  readonly capabilities: MembershipOperationCapabilities
286
283
  }
287
284
 
@@ -377,7 +374,7 @@ export interface ReactivateMemberResult {
377
374
  /** `"session"` reads only the cookie; `"any"` reads a bearer access token, else the cookie. */
378
375
  export type AuthCredentialSource = "session" | "any"
379
376
 
380
- export interface AuthSessionResolutionOptions extends AuthSessionAudienceOptions {
377
+ export interface AuthSessionResolutionOptions {
381
378
  readonly credentialSource?: AuthCredentialSource
382
379
  /** Marks this request as eligible to renew a near-expiry browser session. */
383
380
  readonly sessionActivity?: "foreground"
@@ -385,7 +382,6 @@ export interface AuthSessionResolutionOptions extends AuthSessionAudienceOptions
385
382
 
386
383
  /** Where an invitation link sends its recipient. */
387
384
  export interface InvitationDestination {
388
- readonly audience: AuthSessionAudience
389
385
  readonly requestOrigin: string
390
386
  readonly returnTo: string
391
387
  }
@@ -22,8 +22,6 @@ export const MAX_AUTH_INVITATION_TTL_MS = 30 * DAY
22
22
  */
23
23
  export const DEFAULT_AUTH_SESSION_CACHE_TTL_MS = 5_000
24
24
 
25
- export { resolveAuthSessionAudience } from "./audience"
26
-
27
25
  export function resolveAuthConfig(config: SixbAuthConfig | undefined): ResolvedAuthConfig {
28
26
  if (!config) {
29
27
  return {
@@ -10,7 +10,6 @@
10
10
  * is unrestricted.
11
11
  */
12
12
 
13
- import type { AuthSessionAudience } from "../auth/audience"
14
13
  import {
15
14
  type ResolvedRuntimeAuthorization,
16
15
  resolveExecutionScopeAuthorization,
@@ -18,12 +17,11 @@ import {
18
17
  } from "../execution/authorization"
19
18
  import type { ExecutionContext, RuntimeAuthorization } from "../execution/types"
20
19
  import { AuthorizationError } from "./errors"
21
- import type { GrantKind } from "./grant-kinds"
20
+ import type { SingletonGrantKind, TargetedGrantKind } from "./grant-kinds"
22
21
  import type { AuthorizationContext, GrantIndex } from "./types"
23
22
 
24
23
  /** Something a principal may attempt, paired with the resource it targets. */
25
24
  export type AuthzRequest =
26
- | { readonly kind: "application.access"; readonly audience: AuthSessionAudience }
27
25
  | { readonly kind: "object.view"; readonly objectTypeId: string }
28
26
  | { readonly kind: "dataset.view"; readonly datasetId: string }
29
27
  | { readonly kind: "object.edit"; readonly objectTypeId: string }
@@ -59,13 +57,11 @@ interface AuthorizedRuntime {
59
57
  // the two can never drift. `kind` is the resolved-index key, so enforcement is
60
58
  // a direct lookup with no per-target dispatch.
61
59
  type Atom =
62
- | { readonly kind: "run:agent" }
63
- | { readonly kind: Exclude<GrantKind, "run:agent">; readonly id: string }
60
+ | { readonly kind: SingletonGrantKind }
61
+ | { readonly kind: TargetedGrantKind; readonly id: string }
64
62
 
65
63
  function atomsFor(request: AuthzRequest): readonly Atom[] {
66
64
  switch (request.kind) {
67
- case "application.access":
68
- return [{ kind: "access:application", id: request.audience }]
69
65
  case "object.view":
70
66
  return [{ kind: "view:object", id: request.objectTypeId }]
71
67
  case "dataset.view":
@@ -87,11 +83,11 @@ function atomsFor(request: AuthzRequest): readonly Atom[] {
87
83
  case "agent.run":
88
84
  return [{ kind: "run:agent" }]
89
85
  case "logs.observe":
90
- return [{ kind: "observe:logs", id: "logs" }]
86
+ return [{ kind: "observe:logs" }]
91
87
  case "aiUsage.observe":
92
- return [{ kind: "observe:aiUsage", id: "aiUsage" }]
88
+ return [{ kind: "observe:aiUsage" }]
93
89
  case "aiUsage.manage":
94
- return [{ kind: "manage:aiUsage", id: "aiUsage" }]
90
+ return [{ kind: "manage:aiUsage" }]
95
91
  case "connector.manage":
96
92
  return [{ kind: "manage:connector", id: request.connectorId }]
97
93
  case "object.query":
@@ -100,20 +96,11 @@ function atomsFor(request: AuthzRequest): readonly Atom[] {
100
96
  }
101
97
 
102
98
  function atomKey(atom: Atom): string {
103
- if (atom.kind === "run:agent") return atom.kind
104
- if (
105
- atom.kind === "observe:logs" ||
106
- atom.kind === "observe:aiUsage" ||
107
- atom.kind === "manage:aiUsage"
108
- ) {
109
- return atom.kind
110
- }
111
- return `${atom.kind}:${atom.id}`
99
+ return "id" in atom ? `${atom.kind}:${atom.id}` : atom.kind
112
100
  }
113
101
 
114
102
  function holds(grants: GrantIndex, atom: Atom): boolean {
115
- if (atom.kind === "run:agent") return grants[atom.kind]
116
- return grants[atom.kind].has(atom.id)
103
+ return "id" in atom ? grants[atom.kind].has(atom.id) : grants[atom.kind]
117
104
  }
118
105
 
119
106
  /** Resolve a request against a principal's grants. Never throws. */
@@ -267,8 +254,6 @@ function deniedMessage(
267
254
  ): string {
268
255
  const principalId = authorization?.principal.id ?? "unknown"
269
256
  switch (request.kind) {
270
- case "application.access":
271
- return `[Sixb] Principal '${principalId}' is not allowed to access application '${request.audience}'.`
272
257
  case "object.view":
273
258
  return `[Sixb] Principal '${principalId}' is not allowed to view object type '${request.objectTypeId}'.`
274
259
  case "dataset.view":
@@ -8,10 +8,9 @@
8
8
  * entry in `GRANT_KINDS` plus the compile errors that forces at every consumer.
9
9
  */
10
10
 
11
- import type { AgentRunGrant, GrantDefinition } from "../security/types"
11
+ import type { GrantDefinition } from "../security/types"
12
12
 
13
13
  export type GrantKind =
14
- | "access:application"
15
14
  | "view:object"
16
15
  | "view:dataset"
17
16
  | "edit:object"
@@ -27,12 +26,12 @@ export type GrantKind =
27
26
  | "manage:connector"
28
27
  | "manage:aiUsage"
29
28
 
30
- export type SingletonGrantKind = "run:agent"
29
+ /** Capabilities over one project-wide surface: held or not, with no ids to select. */
30
+ export type SingletonGrantKind = "run:agent" | "observe:logs" | "observe:aiUsage" | "manage:aiUsage"
31
31
  export type TargetedGrantKind = Exclude<GrantKind, SingletonGrantKind>
32
32
 
33
33
  /** Registered id universes a grant kind ranges over, plus subtype expansion. */
34
34
  export interface GrantUniverse {
35
- readonly applicationIds: ReadonlySet<string>
36
35
  readonly objectTypeIds: ReadonlySet<string>
37
36
  readonly datasetIds: ReadonlySet<string>
38
37
  readonly actionIds: ReadonlySet<string>
@@ -40,9 +39,7 @@ export interface GrantUniverse {
40
39
  readonly workflowIds: ReadonlySet<string>
41
40
  readonly syncIds: ReadonlySet<string>
42
41
  readonly pipelineIds: ReadonlySet<string>
43
- readonly observableIds: ReadonlySet<string>
44
42
  readonly connectorIds: ReadonlySet<string>
45
- readonly manageableIds: ReadonlySet<string>
46
43
  readonly getSubTypes: (objectTypeId: string) => readonly string[]
47
44
  }
48
45
 
@@ -76,11 +73,6 @@ export const GRANT_KINDS: {
76
73
  ? SingletonGrantKindSpec
77
74
  : TargetedGrantKindSpec
78
75
  } = {
79
- "access:application": {
80
- universeKey: "applicationIds",
81
- subject: "application",
82
- fix: "Use an application exported from '@sixb/core'.",
83
- },
84
76
  "view:object": {
85
77
  universeKey: "objectTypeIds",
86
78
  subject: "object type",
@@ -136,13 +128,13 @@ export const GRANT_KINDS: {
136
128
  fix: "Configure models.language and use the exported agent reference in can.run(agent).",
137
129
  },
138
130
  "observe:logs": {
139
- universeKey: "observableIds",
140
- subject: "observability surface",
131
+ singleton: true,
132
+ subject: "logs",
141
133
  fix: 'Use can.observe("logs").',
142
134
  },
143
135
  "observe:aiUsage": {
144
- universeKey: "observableIds",
145
- subject: "observability surface",
136
+ singleton: true,
137
+ subject: "AI usage",
146
138
  fix: "Use can.observe(agent.usage).",
147
139
  },
148
140
  "manage:connector": {
@@ -151,25 +143,27 @@ export const GRANT_KINDS: {
151
143
  fix: "Add it to 'connectors/' or pass it to createSixb({ connectors }).",
152
144
  },
153
145
  "manage:aiUsage": {
154
- universeKey: "manageableIds",
155
- subject: "management surface",
146
+ singleton: true,
147
+ subject: "AI usage",
156
148
  fix: "Use can.manage(agent.usage).",
157
149
  },
158
150
  }
159
151
 
160
152
  export const GRANT_KIND_KEYS = Object.keys(GRANT_KINDS) as readonly GrantKind[]
153
+ export const SINGLETON_GRANT_KIND_KEYS = GRANT_KIND_KEYS.filter(
154
+ (kind): kind is SingletonGrantKind => "singleton" in GRANT_KINDS[kind]
155
+ )
161
156
  export const TARGETED_GRANT_KIND_KEYS = GRANT_KIND_KEYS.filter(
162
- (kind): kind is TargetedGrantKind => kind !== "run:agent"
157
+ (kind): kind is TargetedGrantKind => !("singleton" in GRANT_KINDS[kind])
163
158
  )
164
159
 
160
+ export function isSingletonGrantKind(kind: GrantKind): kind is SingletonGrantKind {
161
+ return "singleton" in GRANT_KINDS[kind]
162
+ }
163
+
165
164
  /** The grant kind a stored grant resolves to. */
166
- export function grantKindOf(grant: AgentRunGrant): SingletonGrantKind
167
- export function grantKindOf(grant: Exclude<GrantDefinition, AgentRunGrant>): TargetedGrantKind
168
- export function grantKindOf(grant: GrantDefinition): GrantKind
169
165
  export function grantKindOf(grant: GrantDefinition): GrantKind {
170
166
  switch (grant.capability) {
171
- case "access":
172
- return "access:application"
173
167
  case "view":
174
168
  return `view:${grant.target}`
175
169
  case "edit":
@@ -196,7 +190,6 @@ export type MutableGrantIndex = {
196
190
 
197
191
  export function emptyGrantSets(): MutableGrantIndex {
198
192
  return {
199
- "access:application": new Set(),
200
193
  "view:object": new Set(),
201
194
  "view:dataset": new Set(),
202
195
  "edit:object": new Set(),
@@ -207,9 +200,9 @@ export function emptyGrantSets(): MutableGrantIndex {
207
200
  "run:sync": new Set(),
208
201
  "run:pipeline": new Set(),
209
202
  "run:agent": false,
210
- "observe:logs": new Set(),
211
- "observe:aiUsage": new Set(),
203
+ "observe:logs": false,
204
+ "observe:aiUsage": false,
212
205
  "manage:connector": new Set(),
213
- "manage:aiUsage": new Set(),
206
+ "manage:aiUsage": false,
214
207
  }
215
208
  }
@@ -1,4 +1,3 @@
1
- export { canAccessApplication, isApplicationAccessControlled } from "./application-access"
2
1
  export type { AuthzDecision, AuthzRequest } from "./decision"
3
2
  export {
4
3
  assertAuthorized,
@@ -5,6 +5,8 @@ import {
5
5
  GRANT_KINDS,
6
6
  type GrantUniverse,
7
7
  grantKindOf,
8
+ isSingletonGrantKind,
9
+ SINGLETON_GRANT_KIND_KEYS,
8
10
  TARGETED_GRANT_KIND_KEYS,
9
11
  } from "./grant-kinds"
10
12
  import type { AuthorizationContext, GrantIndex, ResolvedRole } from "./types"
@@ -14,7 +16,7 @@ import type { AuthorizationContext, GrantIndex, ResolvedRole } from "./types"
14
16
  *
15
17
  * Broad grants (`every.object().except([...])`) expand against the registered
16
18
  * universe; object-type grants also expand to subtypes. Resource grants become
17
- * id sets; the project Agent grant becomes a boolean.
19
+ * id sets; grants on one project-wide surface (the Agent, logs, AI usage) become booleans.
18
20
  * The per-kind universe and subtype rules come from the `GRANT_KINDS` table, so
19
21
  * this loop never enumerates targets by hand.
20
22
  */
@@ -22,11 +24,13 @@ export function resolveRoleGrants(role: RoleDefinition, universe: GrantUniverse)
22
24
  const grants = emptyGrantSets()
23
25
 
24
26
  for (const grant of role.grants) {
25
- if (grant.capability === "run" && grant.target === "agent") {
26
- grants["run:agent"] = true
27
+ const kind = grantKindOf(grant)
28
+ if (isSingletonGrantKind(kind)) {
29
+ grants[kind] = true
27
30
  continue
28
31
  }
29
- const kind = grantKindOf(grant)
32
+ // Every other kind carries a selection; this narrows the grant's type to say so.
33
+ if (!("selection" in grant)) continue
30
34
  const spec = GRANT_KINDS[kind]
31
35
  expandSelection(
32
36
  grant.selection,
@@ -89,8 +93,8 @@ export function resolveAuthorizationContext(input: {
89
93
  }
90
94
 
91
95
  roleIds.push(role.id)
92
- if (role.grants["run:agent"]) {
93
- grants["run:agent"] = true
96
+ for (const kind of SINGLETON_GRANT_KIND_KEYS) {
97
+ if (role.grants[kind]) grants[kind] = true
94
98
  }
95
99
  for (const kind of TARGETED_GRANT_KIND_KEYS) {
96
100
  for (const id of role.grants[kind]) {
@@ -10,7 +10,6 @@ import type {
10
10
 
11
11
  const SERVICES = {
12
12
  api: "http",
13
- atlas: "http",
14
13
  app: "http",
15
14
  orchestrator: "singleton",
16
15
  scheduler: "singleton",
@@ -29,7 +29,7 @@ export interface DeployConfig {
29
29
  export type DeployEnv = Readonly<Record<string, string>>
30
30
 
31
31
  /** The services a browser or client reaches through a public domain. */
32
- export type DeployHttpServiceName = "api" | "atlas" | "app"
32
+ export type DeployHttpServiceName = "api" | "app"
33
33
 
34
34
  /** The services that must run as exactly one process: a second would duplicate their work. */
35
35
  export type DeploySingletonServiceName = "orchestrator" | "scheduler" | "rules"
@@ -40,7 +40,6 @@ export type DeployWorkerType = "sync" | "agent" | "pipeline" | "projection" | "w
40
40
 
41
41
  export interface DeployServicesConfig {
42
42
  readonly api?: boolean | DeployHttpServiceConfig
43
- readonly atlas?: boolean | DeployHttpServiceConfig
44
43
  readonly app?: boolean | DeployHttpServiceConfig
45
44
  readonly orchestrator?: boolean | DeploySingletonServiceConfig
46
45
  readonly scheduler?: boolean | DeploySingletonServiceConfig
@@ -55,7 +55,9 @@ function target(value: unknown): void {
55
55
 
56
56
  function services(value: unknown): void {
57
57
  const config = record(value, "services")
58
- knownKeys(config, DEPLOY_SERVICES, "services")
58
+ knownKeys(config, DEPLOY_SERVICES, "services", {
59
+ atlas: "Atlas's pages are part of the app now; remove the setting and configure `app`.",
60
+ })
59
61
 
60
62
  for (const service of DEPLOY_SERVICES) {
61
63
  const override = config[service]
@@ -1,7 +1,12 @@
1
1
  import { isDeepStrictEqual } from "node:util"
2
2
  import { agentServiceAccountId } from "../agents/identity"
3
3
  import type { Principal } from "../auth"
4
- import { TARGETED_GRANT_KIND_KEYS, type TargetedGrantKind } from "../authorization/grant-kinds"
4
+ import {
5
+ SINGLETON_GRANT_KIND_KEYS,
6
+ type SingletonGrantKind,
7
+ TARGETED_GRANT_KIND_KEYS,
8
+ type TargetedGrantKind,
9
+ } from "../authorization/grant-kinds"
5
10
  import type { AuthorizationContext, GrantIndex } from "../authorization/types"
6
11
  import { createSixbError } from "../errors/internal"
7
12
  import type { ObjectRef } from "../ontology"
@@ -586,10 +591,11 @@ function snapshotAuthorizationContext(
586
591
  for (const kind of TARGETED_GRANT_KIND_KEYS) {
587
592
  grants[kind] = new ImmutableGrantSet(context.grants[kind])
588
593
  }
589
- const frozenGrants: GrantIndex = Object.freeze({
590
- ...grants,
591
- "run:agent": context.grants["run:agent"],
592
- })
594
+ const singletons = {} as Record<SingletonGrantKind, boolean>
595
+ for (const kind of SINGLETON_GRANT_KIND_KEYS) {
596
+ singletons[kind] = context.grants[kind]
597
+ }
598
+ const frozenGrants: GrantIndex = Object.freeze({ ...grants, ...singletons })
593
599
  return Object.freeze({
594
600
  principal,
595
601
  ...(context.sessionId === undefined ? {} : { sessionId: context.sessionId }),
package/src/index.ts CHANGED
@@ -391,8 +391,6 @@ export {
391
391
 
392
392
  export type {
393
393
  AuthCookieOptions,
394
- AuthSessionAudience,
395
- AuthSessionAudienceOptions,
396
394
  AuthSessionOptions,
397
395
  AuthStrategy,
398
396
  AuthStrategyKind,
@@ -401,22 +399,14 @@ export type {
401
399
  Principal,
402
400
  SixbAuthConfig,
403
401
  } from "./auth"
404
- export {
405
- DEFAULT_AUTH_SESSION_AUDIENCE,
406
- isValidAuthSessionAudience,
407
- principalsEqual,
408
- resolveAuthSessionAudience,
409
- SYSTEM_PRINCIPAL,
410
- } from "./auth"
402
+ export { principalsEqual, SYSTEM_PRINCIPAL } from "./auth"
411
403
 
412
404
  // ── Authorization ──────────────────────────────────────────
413
405
 
414
406
  export type { AuthorizationContext, GrantIndex, GrantKind } from "./authorization"
415
407
  export {
416
408
  AuthorizationError,
417
- canAccessApplication,
418
409
  isAllowed,
419
- isApplicationAccessControlled,
420
410
  resolveAuthorizationContext,
421
411
  } from "./authorization"
422
412
 
@@ -440,10 +430,8 @@ export type {
440
430
  // ── Security Definitions ───────────────────────────────────
441
431
 
442
432
  export type {
443
- AccessGrant,
444
433
  AgentRunGrant,
445
434
  AppendGrant,
446
- ApplicationDefinition,
447
435
  ApplyGrant,
448
436
  BreadthSelector,
449
437
  BreadthTarget,
@@ -476,7 +464,6 @@ export type {
476
464
  ViewGrantTarget,
477
465
  } from "./security"
478
466
  export {
479
- applications,
480
467
  can,
481
468
  defineGroup,
482
469
  defineMarking,
@@ -58,9 +58,9 @@ async function executeEmbedding(
58
58
  if (purpose !== undefined && purpose !== "document" && purpose !== "query") {
59
59
  throw new TypeError("[SixbModels] Embedding purpose must be 'document' or 'query'.")
60
60
  }
61
+ // The caller owns the deadline: only it knows whether anyone is waiting for the result.
61
62
  const signal = session.signal(input.signal)
62
- const requestSignal = AbortSignal.any([signal, AbortSignal.timeout(30_000)])
63
- requestSignal.throwIfAborted()
63
+ signal.throwIfAborted()
64
64
  if (!texts.length) return { vectors: [] }
65
65
 
66
66
  const accounting = await session.accounting()
@@ -72,7 +72,7 @@ async function executeEmbedding(
72
72
  "[SixbModels] Resolved embedding model identity does not match the selected model."
73
73
  )
74
74
  }
75
- requestSignal.throwIfAborted()
75
+ signal.throwIfAborted()
76
76
  const callId = `call_${randomUUID()}`
77
77
  const tokens = texts.reduce(
78
78
  (sum, text) => sum + Math.ceil(new TextEncoder().encode(text).byteLength / 4),
@@ -92,8 +92,8 @@ async function executeEmbedding(
92
92
 
93
93
  let result: EmbeddingModelResult
94
94
  try {
95
- requestSignal.throwIfAborted()
96
- result = await model.embed({ texts, purpose, signal: requestSignal })
95
+ signal.throwIfAborted()
96
+ result = await model.embed({ texts, purpose, signal })
97
97
  } catch (error) {
98
98
  if (error instanceof EmbeddingModelResponseError) {
99
99
  await recordEmbedding(accounting, model, callId, error.metadata)
@@ -105,7 +105,7 @@ async function executeEmbedding(
105
105
  }
106
106
  // Account before cancellation, vector validation or the materializer's optimistic write.
107
107
  await recordEmbedding(accounting, model, callId, result ?? {})
108
- requestSignal.throwIfAborted()
108
+ signal.throwIfAborted()
109
109
  return result
110
110
  }
111
111
 
@@ -5,6 +5,10 @@ A named profile identifies a derived representation, separate from object proper
5
5
  Indexing sends embedding purpose `document`; search sends `query`. The execution wrapper preserves
6
6
  that role through model resolution, admission and accounting. Symmetric providers may ignore it.
7
7
 
8
+ Each caller sets its own deadline; the execution wrapper adds none. A search has someone waiting
9
+ and gives up after 30 seconds. Indexing, automatic or explicit, waits five minutes: the provider
10
+ bills a call whose response is abandoned, and an abandoned automatic call is a terminal failure.
11
+
8
12
  Vector candidates may come from filters, traversals, explicit refs or set operations. Canonical
9
13
  validation requires one concrete result type and admits every intermediate type, edge and source
10
14
  property. Model lookup uses that resolved result type, not the query's initial type. SQL ranks the
@@ -6,7 +6,12 @@ import type { PreparedObjectVector } from "../../materialization/vectors"
6
6
  import { sameEmbeddingModel } from "../../models/embedding-model"
7
7
  import { getOntologyMutationRuntime } from "../../runtime/ontology-mutations"
8
8
  import type { ExecutionObjectContext } from "../context"
9
- import { normalizeVector, vectorConfiguration, vectorSources } from "./profile"
9
+ import {
10
+ INDEXING_EMBEDDING_TIMEOUT_MS,
11
+ normalizeVector,
12
+ vectorConfiguration,
13
+ vectorSources,
14
+ } from "./profile"
10
15
  import type { ObjectVectorHandle } from "./types"
11
16
 
12
17
  export function createObjectVectorHandle(
@@ -65,7 +70,11 @@ export function createObjectVectorHandle(
65
70
  }
66
71
 
67
72
  // Network work never holds a storage transaction or retries an obsolete computation.
68
- const result = await model.embed({ texts: [input.text], purpose: "document" })
73
+ const result = await model.embed({
74
+ texts: [input.text],
75
+ purpose: "document",
76
+ signal: AbortSignal.timeout(INDEXING_EMBEDDING_TIMEOUT_MS),
77
+ })
69
78
  if (!Array.isArray(result?.vectors) || result.vectors.length !== 1) {
70
79
  throw new MaterializationValidationError(
71
80
  "Embedding model must return exactly one vector for one input text."
@@ -11,7 +11,7 @@ import { ModelExecutionSession } from "../../models/execution/session"
11
11
  import type { SixbHostContext } from "../../runtime/types"
12
12
  import type { VectorIndexingWork } from "../../storage/ontology/vector-indexing"
13
13
  import { fail, retryAt, VectorIndexingDeferred } from "./indexing-shared"
14
- import { normalizeVector } from "./profile"
14
+ import { INDEXING_EMBEDDING_TIMEOUT_MS, normalizeVector } from "./profile"
15
15
 
16
16
  export interface PreparedIndexingWork {
17
17
  readonly work: VectorIndexingWork
@@ -66,7 +66,7 @@ export async function generateVectors(
66
66
  const result = await model.embed({
67
67
  texts: entries.map((entry) => entry.input.text),
68
68
  purpose: "document",
69
- signal,
69
+ signal: AbortSignal.any([signal, AbortSignal.timeout(INDEXING_EMBEDDING_TIMEOUT_MS)]),
70
70
  })
71
71
  const values = normalizeEmbeddingResult(
72
72
  result,
@@ -4,6 +4,11 @@ import type { ObjectVectorSearchProfile } from "../../ontology/types"
4
4
 
5
5
  export const MAX_VECTOR_K = 1000
6
6
  export const VECTOR_INPUT_VERSION = 1
7
+ /**
8
+ * Nobody waits on indexing, and the provider bills a call whose response is abandoned. The
9
+ * deadline only frees the worker from a dead connection, so it is far longer than a search's.
10
+ */
11
+ export const INDEXING_EMBEDDING_TIMEOUT_MS = 5 * 60_000
7
12
 
8
13
  export function vectorConfiguration(profile: ObjectVectorSearchProfile): string {
9
14
  return sha256Canonical({
@@ -39,7 +39,12 @@ export interface DefineMembershipPolicyOptions {
39
39
  readonly can: readonly MembershipOperation[]
40
40
  }
41
41
 
42
- const MEMBERSHIP_OPERATIONS = new Set<MembershipOperation>(["invite", "assignGroups", "suspend"])
42
+ const MEMBERSHIP_OPERATIONS = new Set<MembershipOperation>([
43
+ "invite",
44
+ "assignGroups",
45
+ "suspend",
46
+ "serviceAccounts",
47
+ ])
43
48
 
44
49
  function assertNonEmptyArray<T>(value: readonly T[], field: string): void {
45
50
  if (value.length === 0) {
@@ -65,7 +70,7 @@ function membershipOperationsFrom(
65
70
  return operations.map((operation) => {
66
71
  if (!MEMBERSHIP_OPERATIONS.has(operation)) {
67
72
  throw new SecurityValidationError(
68
- `[Sixb] ${field} must contain only membership operations: invite, assignGroups, suspend.`
73
+ `[Sixb] ${field} must contain only membership operations: invite, assignGroups, suspend, serviceAccounts.`
69
74
  )
70
75
  }
71
76
 
@@ -20,7 +20,6 @@ import type { ShareDefinition } from "../shares"
20
20
  import type { SyncDefinition } from "../syncs"
21
21
  import type { WorkflowDefinition } from "../workflows/types"
22
22
  import { SecurityValidationError } from "./errors"
23
- import type { ApplicationDefinition } from "./types"
24
23
 
25
24
  /** Capability targets a breadth selector can range over. */
26
25
  export const BREADTH_TARGETS = [
@@ -30,7 +29,6 @@ export const BREADTH_TARGETS = [
30
29
  "workflow",
31
30
  "sync",
32
31
  "pipeline",
33
- "application",
34
32
  "connector",
35
33
  "share",
36
34
  ] as const
@@ -44,7 +42,6 @@ interface BreadthTargetInput {
44
42
  workflow: WorkflowDefinition
45
43
  sync: SyncDefinition
46
44
  pipeline: PipelineDefinition
47
- application: ApplicationDefinition
48
45
  connector: ConnectorDefinition
49
46
  share: ShareDefinition
50
47
  }
@@ -106,7 +103,6 @@ export const every = {
106
103
  workflow: (): BreadthSelector<"workflow"> => all("workflow"),
107
104
  sync: (): BreadthSelector<"sync"> => all("sync"),
108
105
  pipeline: (): BreadthSelector<"pipeline"> => all("pipeline"),
109
- application: (): BreadthSelector<"application"> => all("application"),
110
106
  connector: (): BreadthSelector<"connector"> => all("connector"),
111
107
  share: (): BreadthSelector<"share"> => all("share"),
112
108
  }