@antasphere/chassis-contract 0.0.0-stage → 1.0.1

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 (124) hide show
  1. package/LICENSE +82 -0
  2. package/dist/define.d.ts +177 -0
  3. package/dist/define.d.ts.map +1 -0
  4. package/dist/define.js +35 -0
  5. package/dist/define.js.map +1 -0
  6. package/dist/entitlements.d.ts +265 -0
  7. package/dist/entitlements.d.ts.map +1 -0
  8. package/dist/entitlements.js +155 -0
  9. package/dist/entitlements.js.map +1 -0
  10. package/dist/identity.d.ts +56 -0
  11. package/dist/identity.d.ts.map +1 -0
  12. package/dist/identity.js +2 -0
  13. package/dist/identity.js.map +1 -0
  14. package/dist/index.d.ts +22 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +28 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/routes/index.d.ts +5403 -0
  19. package/dist/routes/index.d.ts.map +1 -0
  20. package/dist/routes/index.js +940 -0
  21. package/dist/routes/index.js.map +1 -0
  22. package/dist/schemas/api-keys.d.ts +54 -0
  23. package/dist/schemas/api-keys.d.ts.map +1 -0
  24. package/dist/schemas/api-keys.js +48 -0
  25. package/dist/schemas/api-keys.js.map +1 -0
  26. package/dist/schemas/audit.d.ts +74 -0
  27. package/dist/schemas/audit.d.ts.map +1 -0
  28. package/dist/schemas/audit.js +65 -0
  29. package/dist/schemas/audit.js.map +1 -0
  30. package/dist/schemas/break-glass.d.ts +42 -0
  31. package/dist/schemas/break-glass.d.ts.map +1 -0
  32. package/dist/schemas/break-glass.js +38 -0
  33. package/dist/schemas/break-glass.js.map +1 -0
  34. package/dist/schemas/cli-auth.d.ts +59 -0
  35. package/dist/schemas/cli-auth.d.ts.map +1 -0
  36. package/dist/schemas/cli-auth.js +68 -0
  37. package/dist/schemas/cli-auth.js.map +1 -0
  38. package/dist/schemas/common.d.ts +96 -0
  39. package/dist/schemas/common.d.ts.map +1 -0
  40. package/dist/schemas/common.js +205 -0
  41. package/dist/schemas/common.js.map +1 -0
  42. package/dist/schemas/demo-passes.d.ts +90 -0
  43. package/dist/schemas/demo-passes.d.ts.map +1 -0
  44. package/dist/schemas/demo-passes.js +60 -0
  45. package/dist/schemas/demo-passes.js.map +1 -0
  46. package/dist/schemas/files.d.ts +39 -0
  47. package/dist/schemas/files.d.ts.map +1 -0
  48. package/dist/schemas/files.js +26 -0
  49. package/dist/schemas/files.js.map +1 -0
  50. package/dist/schemas/instance.d.ts +58 -0
  51. package/dist/schemas/instance.d.ts.map +1 -0
  52. package/dist/schemas/instance.js +70 -0
  53. package/dist/schemas/instance.js.map +1 -0
  54. package/dist/schemas/invitations.d.ts +100 -0
  55. package/dist/schemas/invitations.d.ts.map +1 -0
  56. package/dist/schemas/invitations.js +55 -0
  57. package/dist/schemas/invitations.js.map +1 -0
  58. package/dist/schemas/me.d.ts +81 -0
  59. package/dist/schemas/me.d.ts.map +1 -0
  60. package/dist/schemas/me.js +178 -0
  61. package/dist/schemas/me.js.map +1 -0
  62. package/dist/schemas/members.d.ts +60 -0
  63. package/dist/schemas/members.d.ts.map +1 -0
  64. package/dist/schemas/members.js +43 -0
  65. package/dist/schemas/members.js.map +1 -0
  66. package/dist/schemas/projects.d.ts +232 -0
  67. package/dist/schemas/projects.d.ts.map +1 -0
  68. package/dist/schemas/projects.js +140 -0
  69. package/dist/schemas/projects.js.map +1 -0
  70. package/dist/schemas/scope.d.ts +14 -0
  71. package/dist/schemas/scope.d.ts.map +1 -0
  72. package/dist/schemas/scope.js +5 -0
  73. package/dist/schemas/scope.js.map +1 -0
  74. package/dist/schemas/setup.d.ts +28 -0
  75. package/dist/schemas/setup.d.ts.map +1 -0
  76. package/dist/schemas/setup.js +28 -0
  77. package/dist/schemas/setup.js.map +1 -0
  78. package/dist/schemas/sso-connect.d.ts +30 -0
  79. package/dist/schemas/sso-connect.d.ts.map +1 -0
  80. package/dist/schemas/sso-connect.js +38 -0
  81. package/dist/schemas/sso-connect.js.map +1 -0
  82. package/dist/schemas/sso-logout.d.ts +17 -0
  83. package/dist/schemas/sso-logout.d.ts.map +1 -0
  84. package/dist/schemas/sso-logout.js +16 -0
  85. package/dist/schemas/sso-logout.js.map +1 -0
  86. package/dist/schemas/teams.d.ts +100 -0
  87. package/dist/schemas/teams.d.ts.map +1 -0
  88. package/dist/schemas/teams.js +84 -0
  89. package/dist/schemas/teams.js.map +1 -0
  90. package/dist/schemas/workspaces.d.ts +99 -0
  91. package/dist/schemas/workspaces.d.ts.map +1 -0
  92. package/dist/schemas/workspaces.js +96 -0
  93. package/dist/schemas/workspaces.js.map +1 -0
  94. package/dist/seams.d.ts +185 -0
  95. package/dist/seams.d.ts.map +1 -0
  96. package/dist/seams.js +37 -0
  97. package/dist/seams.js.map +1 -0
  98. package/package.json +41 -3
  99. package/src/define.ts +64 -0
  100. package/src/entitlements.ts +340 -0
  101. package/src/identity.ts +49 -0
  102. package/src/index.ts +37 -0
  103. package/src/routes/index.ts +1146 -0
  104. package/src/schemas/api-keys.ts +53 -0
  105. package/src/schemas/audit.ts +74 -0
  106. package/src/schemas/break-glass.ts +46 -0
  107. package/src/schemas/cli-auth.ts +78 -0
  108. package/src/schemas/common.ts +206 -0
  109. package/src/schemas/demo-passes.ts +73 -0
  110. package/src/schemas/files.ts +30 -0
  111. package/src/schemas/instance.ts +71 -0
  112. package/src/schemas/invitations.ts +66 -0
  113. package/src/schemas/me.ts +184 -0
  114. package/src/schemas/members.ts +53 -0
  115. package/src/schemas/projects.ts +174 -0
  116. package/src/schemas/scope.ts +18 -0
  117. package/src/schemas/setup.ts +31 -0
  118. package/src/schemas/sso-connect.ts +40 -0
  119. package/src/schemas/sso-logout.ts +17 -0
  120. package/src/schemas/teams.ts +101 -0
  121. package/src/schemas/workspaces.ts +109 -0
  122. package/src/seams.ts +202 -0
  123. package/test/define.test.ts +59 -0
  124. package/README.md +0 -3
@@ -0,0 +1,100 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Teams: named groups of the workspace's people, on BOTH editions with the
4
+ * same routes and screens; only the source differs (PRDCT-2813). On the
5
+ * self-hosted edition, and in a cloud-local workspace, owners and admins
6
+ * make and shape them here; in a hub-origin workspace they are the hub's
7
+ * projection, read here and managed on the account site (every write answers
8
+ * `hub_managed`). Every non-guest member reads the teams and a team's
9
+ * members. A team holds the workspace's MEMBERSHIPS, so it can never hold an
10
+ * outsider, and a person leaves every team with their membership.
11
+ *
12
+ * The shapes mirror the hub's own teams contract (its `schemas/teams.ts`), so
13
+ * the two Teams pages read the same; a person is named by their user id or
14
+ * their email, as on this tool's project routes.
15
+ */
16
+ /** A team's slug: lowercase words joined by single dashes, unique within a workspace. */
17
+ export declare const teamSlugSchema: z.ZodString;
18
+ export declare const teamSchema: z.ZodObject<{
19
+ id: z.ZodString;
20
+ slug: z.ZodString;
21
+ name: z.ZodString;
22
+ membersCount: z.ZodNumber;
23
+ isMember: z.ZodBoolean;
24
+ hubTeamId: z.ZodNullable<z.ZodString>;
25
+ createdAt: z.ZodString;
26
+ updatedAt: z.ZodString;
27
+ }, z.core.$strip>;
28
+ export type Team = z.infer<typeof teamSchema>;
29
+ export declare const teamsListSchema: z.ZodObject<{
30
+ teams: z.ZodArray<z.ZodObject<{
31
+ id: z.ZodString;
32
+ slug: z.ZodString;
33
+ name: z.ZodString;
34
+ membersCount: z.ZodNumber;
35
+ isMember: z.ZodBoolean;
36
+ hubTeamId: z.ZodNullable<z.ZodString>;
37
+ createdAt: z.ZodString;
38
+ updatedAt: z.ZodString;
39
+ }, z.core.$strip>>;
40
+ nextCursor: z.ZodNullable<z.ZodString>;
41
+ }, z.core.$strip>;
42
+ export type TeamsList = z.infer<typeof teamsListSchema>;
43
+ export declare const teamsListQuerySchema: z.ZodObject<{
44
+ cursor: z.ZodOptional<z.ZodString>;
45
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
46
+ }, z.core.$strip>;
47
+ export declare const teamCreateSchema: z.ZodObject<{
48
+ name: z.ZodString;
49
+ slug: z.ZodOptional<z.ZodString>;
50
+ }, z.core.$strip>;
51
+ export type TeamCreate = z.infer<typeof teamCreateSchema>;
52
+ export declare const teamUpdateSchema: z.ZodObject<{
53
+ name: z.ZodOptional<z.ZodString>;
54
+ slug: z.ZodOptional<z.ZodString>;
55
+ }, z.core.$strip>;
56
+ export type TeamUpdate = z.infer<typeof teamUpdateSchema>;
57
+ export declare const teamMemberSchema: z.ZodObject<{
58
+ userId: z.ZodString;
59
+ email: z.ZodString;
60
+ name: z.ZodString;
61
+ role: z.ZodEnum<{
62
+ owner: "owner";
63
+ admin: "admin";
64
+ member: "member";
65
+ }>;
66
+ isActive: z.ZodBoolean;
67
+ addedAt: z.ZodString;
68
+ }, z.core.$strip>;
69
+ export type TeamMemberInfo = z.infer<typeof teamMemberSchema>;
70
+ export declare const teamMembersListSchema: z.ZodObject<{
71
+ members: z.ZodArray<z.ZodObject<{
72
+ userId: z.ZodString;
73
+ email: z.ZodString;
74
+ name: z.ZodString;
75
+ role: z.ZodEnum<{
76
+ owner: "owner";
77
+ admin: "admin";
78
+ member: "member";
79
+ }>;
80
+ isActive: z.ZodBoolean;
81
+ addedAt: z.ZodString;
82
+ }, z.core.$strip>>;
83
+ nextCursor: z.ZodNullable<z.ZodString>;
84
+ }, z.core.$strip>;
85
+ export type TeamMembersList = z.infer<typeof teamMembersListSchema>;
86
+ /**
87
+ * Seat one of the workspace's OWN active non-guest members, named by user id
88
+ * or by email: exactly one of the two. Nothing is invited or minted here.
89
+ */
90
+ export declare const teamMemberAddSchema: z.ZodObject<{
91
+ userId: z.ZodOptional<z.ZodString>;
92
+ email: z.ZodOptional<z.ZodEmail>;
93
+ }, z.core.$strip>;
94
+ export type TeamMemberAdd = z.infer<typeof teamMemberAddSchema>;
95
+ /** `{id}` the team (a uuid); `{userId}` Better Auth's text id: bounded free text, no control characters. */
96
+ export declare const teamMemberParamsSchema: z.ZodObject<{
97
+ id: z.ZodUUID;
98
+ userId: z.ZodString;
99
+ }, z.core.$strip>;
100
+ //# sourceMappingURL=teams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams.d.ts","sourceRoot":"","sources":["../../src/schemas/teams.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;GAaG;AAEH,yFAAyF;AACzF,eAAO,MAAM,cAAc,aAIjB,CAAC;AAEX,eAAO,MAAM,UAAU;;;;;;;;;iBAcrB,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAE9C,eAAO,MAAM,eAAe;;;;;;;;;;;;iBAG1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,oBAAoB;;;iBAAwB,CAAC;AAE1D,eAAO,MAAM,gBAAgB;;;iBAI3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB;;;iBAKiE,CAAC;AAC/F,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB;;;;;;;;;;;iBAQ3B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE9D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;iBAGhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;iBAO5B,CAAC;AACL,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,4GAA4G;AAC5G,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAC"}
@@ -0,0 +1,84 @@
1
+ import { z } from 'zod';
2
+ import { cursorPageQuerySchema, noControlChars, plainText, workspaceRoleSchema } from './common.js';
3
+ /**
4
+ * Teams: named groups of the workspace's people, on BOTH editions with the
5
+ * same routes and screens; only the source differs (PRDCT-2813). On the
6
+ * self-hosted edition, and in a cloud-local workspace, owners and admins
7
+ * make and shape them here; in a hub-origin workspace they are the hub's
8
+ * projection, read here and managed on the account site (every write answers
9
+ * `hub_managed`). Every non-guest member reads the teams and a team's
10
+ * members. A team holds the workspace's MEMBERSHIPS, so it can never hold an
11
+ * outsider, and a person leaves every team with their membership.
12
+ *
13
+ * The shapes mirror the hub's own teams contract (its `schemas/teams.ts`), so
14
+ * the two Teams pages read the same; a person is named by their user id or
15
+ * their email, as on this tool's project routes.
16
+ */
17
+ /** A team's slug: lowercase words joined by single dashes, unique within a workspace. */
18
+ export const teamSlugSchema = z
19
+ .string()
20
+ .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'lowercase letters and digits, joined by single dashes')
21
+ .min(1)
22
+ .max(60);
23
+ export const teamSchema = z.object({
24
+ id: z.string(),
25
+ slug: z.string(),
26
+ name: z.string(),
27
+ membersCount: z.number().int(),
28
+ /** The caller belongs to this team. */
29
+ isMember: z.boolean(),
30
+ /**
31
+ * The hub's team id when the team is the account site's projection (the
32
+ * Manage link opens it there); null for a team the tool owns.
33
+ */
34
+ hubTeamId: z.string().nullable(),
35
+ createdAt: z.string(),
36
+ updatedAt: z.string()
37
+ });
38
+ export const teamsListSchema = z.object({
39
+ teams: z.array(teamSchema),
40
+ nextCursor: z.string().nullable()
41
+ });
42
+ export const teamsListQuerySchema = cursorPageQuerySchema;
43
+ export const teamCreateSchema = z.object({
44
+ name: plainText(1, 80),
45
+ /** Absent: derived from the name (lowercased, non-alphanumerics to dashes, cut to 60). */
46
+ slug: teamSlugSchema.optional()
47
+ });
48
+ export const teamUpdateSchema = z
49
+ .object({
50
+ name: plainText(1, 80).optional(),
51
+ slug: teamSlugSchema.optional()
52
+ })
53
+ .refine((b) => b.name !== undefined || b.slug !== undefined, { error: 'nothing to change' });
54
+ export const teamMemberSchema = z.object({
55
+ userId: z.string(),
56
+ email: z.string(),
57
+ name: z.string(),
58
+ /** The person's role in the WORKSPACE (a team has no roles of its own). */
59
+ role: workspaceRoleSchema,
60
+ isActive: z.boolean(),
61
+ addedAt: z.string()
62
+ });
63
+ export const teamMembersListSchema = z.object({
64
+ members: z.array(teamMemberSchema),
65
+ nextCursor: z.string().nullable()
66
+ });
67
+ /**
68
+ * Seat one of the workspace's OWN active non-guest members, named by user id
69
+ * or by email: exactly one of the two. Nothing is invited or minted here.
70
+ */
71
+ export const teamMemberAddSchema = z
72
+ .object({
73
+ userId: plainText(1, 200).optional(),
74
+ email: z.email().optional()
75
+ })
76
+ .refine((v) => (v.userId === undefined) !== (v.email === undefined), {
77
+ error: 'exactly one of userId or email is required'
78
+ });
79
+ /** `{id}` the team (a uuid); `{userId}` Better Auth's text id: bounded free text, no control characters. */
80
+ export const teamMemberParamsSchema = z.object({
81
+ id: z.uuid(),
82
+ userId: noControlChars(z.string().min(1).max(200))
83
+ });
84
+ //# sourceMappingURL=teams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams.js","sourceRoot":"","sources":["../../src/schemas/teams.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import { z } from 'zod';
2
+ export declare const workspaceLookSchema: z.ZodObject<{
3
+ theme: z.ZodNullable<z.ZodString>;
4
+ pattern: z.ZodNullable<z.ZodString>;
5
+ field: z.ZodNullable<z.ZodNumber>;
6
+ grain: z.ZodNullable<z.ZodNumber>;
7
+ }, z.core.$strip>;
8
+ export type WorkspaceLook = z.infer<typeof workspaceLookSchema>;
9
+ /**
10
+ * POST /api/v1/workspaces — a signed-in person creates ANOTHER workspace from
11
+ * inside the product (PRDCT-2444 self-hosted, PRDCT-2443 cloud). One route,
12
+ * one body, one answer on both editions; the dashboard keys off
13
+ * `/me.canCreateWorkspace` and never sniffs the edition.
14
+ *
15
+ * - Self-hosted: the workspace is created locally with the caller as its
16
+ * active owner, under the operator's per-person cap
17
+ * (`MAX_WORKSPACES_PER_USER`).
18
+ * - Cloud: the organization is created at Antasphere AS THE CALLER, then
19
+ * projected locally before the answer — `workspace.id` is always the
20
+ * LOCAL workspace id, the one `X-Workspace-Id` selects.
21
+ *
22
+ * Sessions only: API keys and OAuth bearers are refused (the route is
23
+ * deliberately absent from the machine scope allowlist). The name is trimmed
24
+ * server-side; a name that is blank once trimmed answers 400. The look the
25
+ * person picked in the dialog rides along, so the workspace is born with it
26
+ * on every member's screen.
27
+ */
28
+ export declare const workspaceCreateSchema: z.ZodObject<{
29
+ name: z.ZodString;
30
+ look: z.ZodOptional<z.ZodObject<{
31
+ theme: z.ZodOptional<z.ZodNullable<z.ZodString>>;
32
+ pattern: z.ZodOptional<z.ZodNullable<z.ZodString>>;
33
+ field: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
34
+ grain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
35
+ }, z.core.$strip>>;
36
+ }, z.core.$strip>;
37
+ export type WorkspaceCreate = z.infer<typeof workspaceCreateSchema>;
38
+ export declare const workspaceCreatedSchema: z.ZodObject<{
39
+ workspace: z.ZodObject<{
40
+ id: z.ZodString;
41
+ name: z.ZodString;
42
+ look: z.ZodObject<{
43
+ theme: z.ZodNullable<z.ZodString>;
44
+ pattern: z.ZodNullable<z.ZodString>;
45
+ field: z.ZodNullable<z.ZodNumber>;
46
+ grain: z.ZodNullable<z.ZodNumber>;
47
+ }, z.core.$strip>;
48
+ }, z.core.$strip>;
49
+ }, z.core.$strip>;
50
+ export type WorkspaceCreated = z.infer<typeof workspaceCreatedSchema>;
51
+ /**
52
+ * PUT /api/v1/me/default-workspace — the workspace a request naming none
53
+ * resolves to, chosen by the person for themselves (PRDCT-2815). `null`
54
+ * clears the choice: the oldest active membership answers again. On the
55
+ * cloud edition the default is a setting of the person's Antasphere account,
56
+ * projected here at every sign-in: the route answers 403 `hub_managed` with
57
+ * the account site to set it on.
58
+ */
59
+ export declare const defaultWorkspaceSetSchema: z.ZodObject<{
60
+ workspaceId: z.ZodNullable<z.ZodString>;
61
+ }, z.core.$strip>;
62
+ export type DefaultWorkspaceSet = z.infer<typeof defaultWorkspaceSetSchema>;
63
+ export declare const defaultWorkspaceSchema: z.ZodObject<{
64
+ defaultWorkspaceId: z.ZodNullable<z.ZodString>;
65
+ }, z.core.$strip>;
66
+ export type DefaultWorkspace = z.infer<typeof defaultWorkspaceSchema>;
67
+ /**
68
+ * PATCH /api/v1/workspace — the ACTIVE workspace's own settings (its name,
69
+ * its look), by an owner or an admin of it, from a browser session. The
70
+ * route names no id: a request works in exactly one workspace (ADR 014),
71
+ * and that is the one it edits. On the cloud edition a hub-origin
72
+ * workspace's NAME is the hub's (P7): a rename answers 403 `hub_managed`
73
+ * with the console to do it at; its look stays a local fact and is
74
+ * accepted.
75
+ */
76
+ export declare const workspaceUpdateSchema: z.ZodObject<{
77
+ name: z.ZodOptional<z.ZodString>;
78
+ look: z.ZodOptional<z.ZodObject<{
79
+ theme: z.ZodOptional<z.ZodNullable<z.ZodString>>;
80
+ pattern: z.ZodOptional<z.ZodNullable<z.ZodString>>;
81
+ field: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
82
+ grain: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
83
+ }, z.core.$strip>>;
84
+ }, z.core.$strip>;
85
+ export type WorkspaceUpdate = z.infer<typeof workspaceUpdateSchema>;
86
+ export declare const workspaceUpdatedSchema: z.ZodObject<{
87
+ workspace: z.ZodObject<{
88
+ id: z.ZodString;
89
+ name: z.ZodString;
90
+ look: z.ZodObject<{
91
+ theme: z.ZodNullable<z.ZodString>;
92
+ pattern: z.ZodNullable<z.ZodString>;
93
+ field: z.ZodNullable<z.ZodNumber>;
94
+ grain: z.ZodNullable<z.ZodNumber>;
95
+ }, z.core.$strip>;
96
+ }, z.core.$strip>;
97
+ }, z.core.$strip>;
98
+ export type WorkspaceUpdated = z.infer<typeof workspaceUpdatedSchema>;
99
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/schemas/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,eAAO,MAAM,mBAAmB;;;;;iBAK9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;iBAGhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,sBAAsB;;;;;;;;;;;iBAOjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB;;iBAEpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,sBAAsB;;iBAGjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;iBAK8D,CAAC;AACjG,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,sBAAsB;;;;;;;;;;;iBAMjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,96 @@
1
+ import { z } from 'zod';
2
+ import { plainText } from './common.js';
3
+ /**
4
+ * A workspace's look: one of the dashboard's theme keys and one pattern key
5
+ * of the brand's library. A fact of the WORKSPACE (every member sees the
6
+ * same tile), kept as two short slugs the server does not interpret: the
7
+ * dashboard owns the catalogue and falls back to its defaults on a key it
8
+ * does not know, so retiring a theme never breaks a workspace. null = the
9
+ * dashboard's default for this workspace.
10
+ */
11
+ const lookKey = z
12
+ .string()
13
+ .regex(/^[a-z][a-z0-9-]{0,31}$/, 'a short lowercase key')
14
+ .nullable();
15
+ /**
16
+ * How much of the field's gradient reaches the page, and how much grain sits
17
+ * on it: 0..1, the workspace's too (they were each browser's until
18
+ * 2026-09-19, so two members never saw the same page). null = the brand's
19
+ * constant.
20
+ */
21
+ const lookLevel = z.number().min(0).max(1).nullable();
22
+ export const workspaceLookSchema = z.object({
23
+ theme: lookKey,
24
+ pattern: lookKey,
25
+ field: lookLevel,
26
+ grain: lookLevel
27
+ });
28
+ /**
29
+ * POST /api/v1/workspaces — a signed-in person creates ANOTHER workspace from
30
+ * inside the product (PRDCT-2444 self-hosted, PRDCT-2443 cloud). One route,
31
+ * one body, one answer on both editions; the dashboard keys off
32
+ * `/me.canCreateWorkspace` and never sniffs the edition.
33
+ *
34
+ * - Self-hosted: the workspace is created locally with the caller as its
35
+ * active owner, under the operator's per-person cap
36
+ * (`MAX_WORKSPACES_PER_USER`).
37
+ * - Cloud: the organization is created at Antasphere AS THE CALLER, then
38
+ * projected locally before the answer — `workspace.id` is always the
39
+ * LOCAL workspace id, the one `X-Workspace-Id` selects.
40
+ *
41
+ * Sessions only: API keys and OAuth bearers are refused (the route is
42
+ * deliberately absent from the machine scope allowlist). The name is trimmed
43
+ * server-side; a name that is blank once trimmed answers 400. The look the
44
+ * person picked in the dialog rides along, so the workspace is born with it
45
+ * on every member's screen.
46
+ */
47
+ export const workspaceCreateSchema = z.object({
48
+ name: plainText(1, 120),
49
+ look: workspaceLookSchema.partial().optional()
50
+ });
51
+ export const workspaceCreatedSchema = z.object({
52
+ workspace: z.object({
53
+ /** The LOCAL workspace id — pass it as `X-Workspace-Id` to work in it. */
54
+ id: z.string(),
55
+ name: z.string(),
56
+ look: workspaceLookSchema
57
+ })
58
+ });
59
+ /**
60
+ * PUT /api/v1/me/default-workspace — the workspace a request naming none
61
+ * resolves to, chosen by the person for themselves (PRDCT-2815). `null`
62
+ * clears the choice: the oldest active membership answers again. On the
63
+ * cloud edition the default is a setting of the person's Antasphere account,
64
+ * projected here at every sign-in: the route answers 403 `hub_managed` with
65
+ * the account site to set it on.
66
+ */
67
+ export const defaultWorkspaceSetSchema = z.object({
68
+ workspaceId: z.string().uuid().nullable()
69
+ });
70
+ export const defaultWorkspaceSchema = z.object({
71
+ /** The LOCAL id of the person's default workspace, or null when none is chosen. */
72
+ defaultWorkspaceId: z.string().nullable()
73
+ });
74
+ /**
75
+ * PATCH /api/v1/workspace — the ACTIVE workspace's own settings (its name,
76
+ * its look), by an owner or an admin of it, from a browser session. The
77
+ * route names no id: a request works in exactly one workspace (ADR 014),
78
+ * and that is the one it edits. On the cloud edition a hub-origin
79
+ * workspace's NAME is the hub's (P7): a rename answers 403 `hub_managed`
80
+ * with the console to do it at; its look stays a local fact and is
81
+ * accepted.
82
+ */
83
+ export const workspaceUpdateSchema = z
84
+ .object({
85
+ name: plainText(1, 120).optional(),
86
+ look: workspaceLookSchema.partial().optional()
87
+ })
88
+ .refine((b) => b.name !== undefined || b.look !== undefined, { message: 'nothing to change' });
89
+ export const workspaceUpdatedSchema = z.object({
90
+ workspace: z.object({
91
+ id: z.string(),
92
+ name: z.string(),
93
+ look: workspaceLookSchema
94
+ })
95
+ });
96
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../src/schemas/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG,CAAC;KACd,MAAM,EAAE;KACR,KAAK,CAAC,wBAAwB,EAAE,uBAAuB,CAAC;KACxD,QAAQ,EAAE,CAAC;AACd;;;;;GAKG;AACH,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,SAAS;CACjB,CAAC,CAAC;AAGH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC;IACvB,IAAI,EAAE,mBAAmB,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC/C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QAClB,0EAA0E;QAC1E,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,mBAAmB;KAC1B,CAAC;CACH,CAAC,CAAC;AAGH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,mFAAmF;IACnF,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAGH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC;KACnC,MAAM,CAAC;IACN,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE;IAClC,IAAI,EAAE,mBAAmB,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC/C,CAAC;KACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAGjG,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QAClB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,IAAI,EAAE,mBAAmB;KAC1B,CAAC;CACH,CAAC,CAAC"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * The central-rail seam: three small interfaces wired through the boot-time
3
+ * module registry. The central account/credits service is NOT part of the
4
+ * template — these interfaces are the socket it plugs into later with zero
5
+ * refactor. Template defaults: LocalIdentityProvider, AllowAllEntitlements,
6
+ * a no-op UsageSink.
7
+ */
8
+ /** Structural Headers so the contract stays lib-agnostic (works in DOM and Node). */
9
+ export interface HeaderReader {
10
+ get(name: string): string | null;
11
+ }
12
+ export interface RequestContext {
13
+ /** Raw request headers (credential material lives here). */
14
+ headers: HeaderReader;
15
+ path: string;
16
+ method: string;
17
+ requestId: string;
18
+ }
19
+ /**
20
+ * The universal per-request workspace selector (user-scoped credential
21
+ * model). EVERY credential kind — session, API key, OAuth bearer — MAY send
22
+ * it to name which of the caller's workspaces this request targets; the
23
+ * resolvers verify an ACTIVE membership of that workspace and resolve to
24
+ * null otherwise (fail closed — no oracle about the workspace's existence).
25
+ * Absent, the user's DEFAULT membership is used, else the deterministic
26
+ * fallback (oldest active membership). The one exception is a PINNED API
27
+ * key (an optional least-privilege pin, and the grandfathered binding of
28
+ * keys minted under the old per-workspace model): it always resolves its
29
+ * pinned workspace, and a header naming a DIFFERENT one is rejected
30
+ * outright (403 workspace_mismatch).
31
+ */
32
+ export declare const ACTIVE_WORKSPACE_HEADER = "x-workspace-id";
33
+ /**
34
+ * The resolved caller of ONE request. A credential identifies a USER; the
35
+ * Principal is still scoped to exactly ONE workspace per request (ADR 014):
36
+ * `workspaceId` is the workspace this request SELECTED via
37
+ * {@link ACTIVE_WORKSPACE_HEADER} (or the user's default), authorized
38
+ * against the caller's own live memberships. A user's OTHER memberships are
39
+ * deliberately not represented here; a request never spans workspaces.
40
+ */
41
+ export interface Principal {
42
+ userId: string;
43
+ email: string;
44
+ name: string;
45
+ workspaceId: string;
46
+ role: 'owner' | 'admin' | 'member';
47
+ /**
48
+ * How the resolved membership came to exist (D2, internal/federation.md §P6):
49
+ * 'local' = ordinary membership (setup, workspace invitation), 'hub' = a
50
+ * hub-org projection (cloud SSO), 'guest' = an external per-resource
51
+ * collaborator minted by the claim path. Origin is a CAPABILITY axis, not
52
+ * a role: a guest resolves like any member but is refused resource creation
53
+ * and workspace-level surfaces (requireNonGuest) on BOTH editions — their
54
+ * access is the per-resource grant (ADR 013), which stays untouched. Every
55
+ * credential path (session, API key, OAuth bearer) reads it live from the
56
+ * membership row backing the request's workspace.
57
+ */
58
+ origin: 'local' | 'hub' | 'guest';
59
+ via: 'session' | 'api_key' | 'oauth';
60
+ /** Scope allowlist for machine principals; null = full role-based (session). */
61
+ scopes: ReadonlySet<string> | null;
62
+ apiKeyId?: string;
63
+ /** Expiry of the presented API key (ISO 8601) — absent for non-expiring keys. */
64
+ apiKeyExpiresAt?: string;
65
+ /** Central account id — undefined in local mode. */
66
+ accountRef?: string;
67
+ /**
68
+ * The credential itself fixed the workspace (an API key pinned to one):
69
+ * the request's selector was checked against the pin, and no default of
70
+ * the person ever moves the request elsewhere. Absent on every credential
71
+ * whose workspace the request selected, or the person's default chose.
72
+ */
73
+ pinned?: true;
74
+ }
75
+ /**
76
+ * Sign-in methods an instance can advertise in discovery. The set is OPEN
77
+ * (ADR 003 reserved this): clients must IGNORE entries they do not
78
+ * recognize, so an edition can add a method — like the cloud edition's
79
+ * 'antasphere' hub SSO — without breaking older SDKs/CLIs. This list is the
80
+ * known vocabulary, not a closed enum.
81
+ */
82
+ export declare const KNOWN_AUTH_METHODS: readonly ["password", "email-otp", "google", "api-key", "oauth", "antasphere"];
83
+ export type KnownAuthMethod = (typeof KNOWN_AUTH_METHODS)[number];
84
+ export interface InstanceAuthDescriptor {
85
+ /** Open set — known values in {@link KNOWN_AUTH_METHODS}; ignore unknown entries. */
86
+ methods: Array<KnownAuthMethod | (string & {})>;
87
+ /** Self-serve password reset is available (requires a configured email driver). */
88
+ passwordReset: boolean;
89
+ /** Self-serve email change is available (requires a configured email driver). */
90
+ emailChange: boolean;
91
+ /** Opt-in per-user 2FA (TOTP + backup codes) is available on this instance. */
92
+ twoFactor: boolean;
93
+ }
94
+ export interface IdentityProvider {
95
+ /** Resolve a request to a live principal (fresh membership check) or null. */
96
+ resolve(ctx: RequestContext): Promise<Principal | null>;
97
+ /** Feeds the instance discovery endpoint. */
98
+ describe(): InstanceAuthDescriptor;
99
+ }
100
+ export interface MeteredAction {
101
+ /** The action key, e.g. 'files.upload' (the route's `meter.key`, namespaced by the tool's price book). */
102
+ key: string;
103
+ quantity: number;
104
+ unit: string;
105
+ }
106
+ export type EntitlementDecision = {
107
+ allowed: true;
108
+ } | {
109
+ allowed: false;
110
+ reason: string;
111
+ };
112
+ /** Per-principal general-API request quota, enforced by the server's quota middleware. */
113
+ export interface RequestQuota {
114
+ /** Sustained allowance per principal per minute. 0 = unlimited (the limiter is skipped). */
115
+ perMinute: number;
116
+ /** Spike cap per principal per second inside the minute window. 0 = no burst smoothing. */
117
+ burstPerSecond: number;
118
+ }
119
+ export interface EntitlementService {
120
+ check(principal: Principal, action: MeteredAction, ctx?: Record<string, unknown>): Promise<EntitlementDecision>;
121
+ /**
122
+ * Request-rate quota for this principal. The template default returns the
123
+ * instance-level env caps for everyone; a plan-aware edition varies it per
124
+ * account/plan. The quota is enforced per authenticated principal identity
125
+ * (API key id / OAuth subject / session user id), never per client header.
126
+ */
127
+ getRequestQuota(principal: Principal): Promise<RequestQuota>;
128
+ }
129
+ /**
130
+ * One metered action, as the tool emits it and the hub ingests it (the
131
+ * billing rail spec, §5 `POST /usage/events`). At-least-once from the tool;
132
+ * exactly-once at the hub by `id`. Paid by the account, reported per user.
133
+ */
134
+ export interface UsageEvent {
135
+ /** ULID — the idempotency key; receivers dedupe on it (at-least-once emission). */
136
+ id: string;
137
+ /** The action key (`meter` is its historical name; the two carry the same value). */
138
+ meter: string;
139
+ actionKey: string;
140
+ quantity: number;
141
+ unit: string;
142
+ occurredAt: string;
143
+ workspaceId: string;
144
+ /** The paying account (the workspace's central account id). */
145
+ accountRef?: string;
146
+ /** The reported user; null when the actor is a resource owner the tool could not name. */
147
+ userId: string | null;
148
+ /** How the action arrived: a session (the dashboard), an API key (the CLI), an OAuth client (an MCP connector). */
149
+ via: 'session' | 'api_key' | 'oauth';
150
+ /** The resource the handler recorded (its audit `resourceType` / `resourceId`), when it recorded one. */
151
+ resourceType?: string;
152
+ resourceId?: string;
153
+ source: {
154
+ instanceId: string;
155
+ edition: string;
156
+ version: string;
157
+ };
158
+ }
159
+ export interface UsageSink {
160
+ emit(event: UsageEvent): Promise<void>;
161
+ }
162
+ /**
163
+ * What a downstream says about a batch it took: the events it did NOT post
164
+ * because the hub would refuse them on their date (PRDCT-2644), each with
165
+ * its reason. The worker sends those to the held queue instead of leaving
166
+ * them counted as rejections at the hub; an empty list, or no outcome at
167
+ * all, means the whole batch was handled.
168
+ */
169
+ export interface UsageBatchOutcome {
170
+ held: ReadonlyArray<{
171
+ id: string;
172
+ reason: string;
173
+ }>;
174
+ }
175
+ /**
176
+ * Where the durable queue hands the events it drained: the no-op locally,
177
+ * the hub poster on cloud. A downstream that takes whole batches gets them
178
+ * as the worker drained them (fifty at most); one that only takes single
179
+ * events is called once per event. A batch downstream may answer an outcome
180
+ * naming the events it held back.
181
+ */
182
+ export interface UsageDownstream extends UsageSink {
183
+ emitBatch?(events: readonly UsageEvent[]): Promise<void | UsageBatchOutcome>;
184
+ }
185
+ //# sourceMappingURL=seams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seams.d.ts","sourceRoot":"","sources":["../src/seams.ts"],"names":[],"mappings":"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"}
package/dist/seams.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The central-rail seam: three small interfaces wired through the boot-time
3
+ * module registry. The central account/credits service is NOT part of the
4
+ * template — these interfaces are the socket it plugs into later with zero
5
+ * refactor. Template defaults: LocalIdentityProvider, AllowAllEntitlements,
6
+ * a no-op UsageSink.
7
+ */
8
+ /**
9
+ * The universal per-request workspace selector (user-scoped credential
10
+ * model). EVERY credential kind — session, API key, OAuth bearer — MAY send
11
+ * it to name which of the caller's workspaces this request targets; the
12
+ * resolvers verify an ACTIVE membership of that workspace and resolve to
13
+ * null otherwise (fail closed — no oracle about the workspace's existence).
14
+ * Absent, the user's DEFAULT membership is used, else the deterministic
15
+ * fallback (oldest active membership). The one exception is a PINNED API
16
+ * key (an optional least-privilege pin, and the grandfathered binding of
17
+ * keys minted under the old per-workspace model): it always resolves its
18
+ * pinned workspace, and a header naming a DIFFERENT one is rejected
19
+ * outright (403 workspace_mismatch).
20
+ */
21
+ export const ACTIVE_WORKSPACE_HEADER = 'x-workspace-id';
22
+ /**
23
+ * Sign-in methods an instance can advertise in discovery. The set is OPEN
24
+ * (ADR 003 reserved this): clients must IGNORE entries they do not
25
+ * recognize, so an edition can add a method — like the cloud edition's
26
+ * 'antasphere' hub SSO — without breaking older SDKs/CLIs. This list is the
27
+ * known vocabulary, not a closed enum.
28
+ */
29
+ export const KNOWN_AUTH_METHODS = [
30
+ 'password',
31
+ 'email-otp',
32
+ 'google',
33
+ 'api-key',
34
+ 'oauth',
35
+ 'antasphere'
36
+ ];
37
+ //# sourceMappingURL=seams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seams.js","sourceRoot":"","sources":["../src/seams.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,gBAAgB,CAAC;AA6CxD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,UAAU;IACV,WAAW;IACX,QAAQ;IACR,SAAS;IACT,OAAO;IACP,YAAY;CACJ,CAAC"}