@smartcrab/contracts-management 0.1.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 (73) hide show
  1. package/LICENSE +202 -0
  2. package/dist/api-keys.d.ts +251 -0
  3. package/dist/api-keys.js +78 -0
  4. package/dist/audit-events.d.ts +94 -0
  5. package/dist/audit-events.js +45 -0
  6. package/dist/billing.d.ts +30 -0
  7. package/dist/billing.js +30 -0
  8. package/dist/clients.d.ts +328 -0
  9. package/dist/clients.js +141 -0
  10. package/dist/common.d.ts +95 -0
  11. package/dist/common.js +99 -0
  12. package/dist/connections.d.ts +201 -0
  13. package/dist/connections.js +107 -0
  14. package/dist/domains.d.ts +167 -0
  15. package/dist/domains.js +74 -0
  16. package/dist/environments.d.ts +194 -0
  17. package/dist/environments.js +101 -0
  18. package/dist/index.d.ts +27 -0
  19. package/dist/index.js +27 -0
  20. package/dist/primitives.d.ts +49 -0
  21. package/dist/primitives.js +56 -0
  22. package/dist/projects.d.ts +78 -0
  23. package/dist/projects.js +49 -0
  24. package/dist/rbac.d.ts +222 -0
  25. package/dist/rbac.js +226 -0
  26. package/dist/usage.d.ts +72 -0
  27. package/dist/usage.js +52 -0
  28. package/dist/user-jobs.d.ts +253 -0
  29. package/dist/user-jobs.js +95 -0
  30. package/dist/user-subresources.d.ts +161 -0
  31. package/dist/user-subresources.js +85 -0
  32. package/dist/users.d.ts +193 -0
  33. package/dist/users.js +112 -0
  34. package/dist/webhooks.d.ts +306 -0
  35. package/dist/webhooks.js +134 -0
  36. package/dist/workspaces.d.ts +172 -0
  37. package/dist/workspaces.js +77 -0
  38. package/package.json +42 -0
  39. package/src/api-keys.test.ts +86 -0
  40. package/src/api-keys.ts +97 -0
  41. package/src/audit-events.test.ts +44 -0
  42. package/src/audit-events.ts +57 -0
  43. package/src/billing.test.ts +57 -0
  44. package/src/billing.ts +46 -0
  45. package/src/clients.test.ts +169 -0
  46. package/src/clients.ts +182 -0
  47. package/src/common.test.ts +102 -0
  48. package/src/common.ts +127 -0
  49. package/src/connections.test.ts +65 -0
  50. package/src/connections.ts +134 -0
  51. package/src/domains.test.ts +48 -0
  52. package/src/domains.ts +104 -0
  53. package/src/environments.test.ts +67 -0
  54. package/src/environments.ts +133 -0
  55. package/src/index.ts +27 -0
  56. package/src/primitives.ts +100 -0
  57. package/src/projects.test.ts +49 -0
  58. package/src/projects.ts +72 -0
  59. package/src/rbac.test.ts +148 -0
  60. package/src/rbac.ts +250 -0
  61. package/src/secret-fields.test.ts +84 -0
  62. package/src/usage.test.ts +57 -0
  63. package/src/usage.ts +66 -0
  64. package/src/user-jobs.test.ts +86 -0
  65. package/src/user-jobs.ts +120 -0
  66. package/src/user-subresources.test.ts +115 -0
  67. package/src/user-subresources.ts +128 -0
  68. package/src/users.test.ts +91 -0
  69. package/src/users.ts +149 -0
  70. package/src/webhooks.test.ts +187 -0
  71. package/src/webhooks.ts +182 -0
  72. package/src/workspaces.test.ts +127 -0
  73. package/src/workspaces.ts +106 -0
package/dist/rbac.d.ts ADDED
@@ -0,0 +1,222 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Dashboard / Management API RBAC (design.md §27.2's role table, §11.2
4
+ * `workspace_members.role`).
5
+ */
6
+ export declare const WORKSPACE_ROLES: readonly ["owner", "admin", "developer", "support", "billing", "viewer"];
7
+ export declare const workspaceRoleSchema: z.ZodEnum<{
8
+ owner: "owner";
9
+ admin: "admin";
10
+ developer: "developer";
11
+ support: "support";
12
+ billing: "billing";
13
+ viewer: "viewer";
14
+ }>;
15
+ export type WorkspaceRole = (typeof WORKSPACE_ROLES)[number];
16
+ /**
17
+ * The full set of grantable Management API scopes. Most use the
18
+ * `<resource>:<action>` form; protocol capabilities such as `introspect` are
19
+ * standalone. This is the declarative permission vocabulary both Management
20
+ * API keys (design.md §11.12) and dashboard roles (design.md §27.2) use.
21
+ */
22
+ export declare const MANAGEMENT_SCOPES: readonly ["workspaces:read", "workspaces:write", "workspace_members:read", "projects:read", "projects:write", "environments:read", "environments:write", "clients:read", "clients:write", "clients:rotate_secret", "connections:read", "connections:write", "domains:read", "domains:write", "users:read", "users:write", "users:block", "users:delete", "user_identities:read", "user_identities:write", "user_passkeys:read", "user_passkeys:write", "user_sessions:read", "user_sessions:write", "user_data_jobs:read", "user_data_jobs:write", "webhooks:read", "webhooks:write", "webhooks:rotate_secret", "webhooks:test", "audit_events:read", "usage:read", "introspect", "billing:read", "billing:write", "api_keys:read", "api_keys:write", "impersonation:create"];
23
+ export declare const managementScopeSchema: z.ZodEnum<{
24
+ "workspaces:read": "workspaces:read";
25
+ "workspaces:write": "workspaces:write";
26
+ "workspace_members:read": "workspace_members:read";
27
+ "projects:read": "projects:read";
28
+ "projects:write": "projects:write";
29
+ "environments:read": "environments:read";
30
+ "environments:write": "environments:write";
31
+ "clients:read": "clients:read";
32
+ "clients:write": "clients:write";
33
+ "clients:rotate_secret": "clients:rotate_secret";
34
+ "connections:read": "connections:read";
35
+ "connections:write": "connections:write";
36
+ "domains:read": "domains:read";
37
+ "domains:write": "domains:write";
38
+ "users:read": "users:read";
39
+ "users:write": "users:write";
40
+ "users:block": "users:block";
41
+ "users:delete": "users:delete";
42
+ "user_identities:read": "user_identities:read";
43
+ "user_identities:write": "user_identities:write";
44
+ "user_passkeys:read": "user_passkeys:read";
45
+ "user_passkeys:write": "user_passkeys:write";
46
+ "user_sessions:read": "user_sessions:read";
47
+ "user_sessions:write": "user_sessions:write";
48
+ "user_data_jobs:read": "user_data_jobs:read";
49
+ "user_data_jobs:write": "user_data_jobs:write";
50
+ "webhooks:read": "webhooks:read";
51
+ "webhooks:write": "webhooks:write";
52
+ "webhooks:rotate_secret": "webhooks:rotate_secret";
53
+ "webhooks:test": "webhooks:test";
54
+ "audit_events:read": "audit_events:read";
55
+ "usage:read": "usage:read";
56
+ introspect: "introspect";
57
+ "billing:read": "billing:read";
58
+ "billing:write": "billing:write";
59
+ "api_keys:read": "api_keys:read";
60
+ "api_keys:write": "api_keys:write";
61
+ "impersonation:create": "impersonation:create";
62
+ }>;
63
+ export type ManagementScope = (typeof MANAGEMENT_SCOPES)[number];
64
+ /**
65
+ * Scopes that let an actor change how a user authenticates: linking/unlinking
66
+ * a social identity or adding/removing a passkey (design.md §12.3/§12.5,
67
+ * §25's "credential"). Deliberately narrower than "anything about the user
68
+ * account" — e.g. blocking a user or editing their display name is an
69
+ * account-state/profile change, not a credential change.
70
+ *
71
+ * design.md §25: "support roleだけではcredentialを変更できない." §27.4 forbids
72
+ * the same category of action during impersonation ("credential変更...は禁止").
73
+ */
74
+ export declare const CREDENTIAL_MUTATING_SCOPES: readonly ["user_identities:write", "user_passkeys:write"];
75
+ /** design.md §27.4: impersonation additionally forbids billing and API key operations. */
76
+ export declare const IMPERSONATION_FORBIDDEN_SCOPES: readonly ["user_identities:write", "user_passkeys:write", "billing:read", "billing:write", "api_keys:read", "api_keys:write"];
77
+ /**
78
+ * design.md §27.2 role → permission table:
79
+ *
80
+ * | Role | 権限 |
81
+ * |-----------|------|
82
+ * | Owner | 全操作、課金、Workspace削除 |
83
+ * | Admin | Project、Environment、ユーザー管理 |
84
+ * | Developer | Client、Connection、Domain、Webhook |
85
+ * | Support | ユーザー閲覧、session失効 |
86
+ * | Billing | 課金・使用量 |
87
+ * | Viewer | 読み取りのみ |
88
+ *
89
+ * `workspace_members:read` grant decision (no dedicated row in the table
90
+ * above — the assignment that added `GET /workspaces/:workspaceId/members`
91
+ * requires a defensible reading of it): granted to owner/admin/support/
92
+ * billing/viewer, withheld from developer. The Developer table lists "Client,
93
+ * Connection, Domain, Webhook" resources, with `introspect` as a standalone
94
+ * OAuth capability for resource-server token validation. The test below
95
+ * ensures the developer role gets no other resource prefixes. Every other
96
+ * role either reads broadly (`viewer`, "読み取りのみ") or needs the roster for
97
+ * its work (`admin` administers the workspace; `support`/`billing` deal with
98
+ * the workspace's people and billing contacts day to day).
99
+ */
100
+ export declare const ROLE_SCOPES: Readonly<Record<WorkspaceRole, readonly ManagementScope[]>>;
101
+ export declare const scopesForRole: (role: WorkspaceRole) => readonly ManagementScope[];
102
+ export declare const roleHasScope: (role: WorkspaceRole, scope: ManagementScope) => boolean;
103
+ /** A scope is read-only when it grants inspection without changing a resource or token state. */
104
+ export declare const isReadOnlyScope: (scope: ManagementScope) => boolean;
105
+ /** design.md §27.4: "OwnerまたはAdmin" may start an impersonation session. */
106
+ export declare const IMPERSONATION_ALLOWED_ROLES: readonly ["owner", "admin"];
107
+ export declare const impersonationAllowedRoleSchema: z.ZodEnum<{
108
+ owner: "owner";
109
+ admin: "admin";
110
+ }>;
111
+ export type ImpersonationAllowedRole = (typeof IMPERSONATION_ALLOWED_ROLES)[number];
112
+ /** design.md §27.4: "最大15分". */
113
+ export declare const IMPERSONATION_MAX_DURATION_MINUTES = 15;
114
+ /** design.md §27.4: "理由入力" is a required, non-empty justification. */
115
+ export declare const impersonationReasonSchema: z.ZodString;
116
+ export declare const impersonationCreateRequestSchema: z.ZodObject<{
117
+ user_id: z.ZodString;
118
+ reason: z.ZodString;
119
+ duration_minutes: z.ZodNumber;
120
+ }, z.core.$strict>;
121
+ export type ImpersonationCreateRequest = z.infer<typeof impersonationCreateRequestSchema>;
122
+ /**
123
+ * design.md §27.4: "UIに常時banner", "全操作をactorとimpersonated userの両方で
124
+ * 監査". The response carries both identities so the dashboard can render the
125
+ * mandatory banner and so every subsequent action can be dual-audited.
126
+ */
127
+ export declare const impersonationSessionSchema: z.ZodObject<{
128
+ actor_user_id: z.ZodString;
129
+ impersonated_user_id: z.ZodString;
130
+ reason: z.ZodString;
131
+ started_at: z.ZodISODateTime;
132
+ expires_at: z.ZodISODateTime;
133
+ forbidden_scopes: z.ZodArray<z.ZodEnum<{
134
+ "workspaces:read": "workspaces:read";
135
+ "workspaces:write": "workspaces:write";
136
+ "workspace_members:read": "workspace_members:read";
137
+ "projects:read": "projects:read";
138
+ "projects:write": "projects:write";
139
+ "environments:read": "environments:read";
140
+ "environments:write": "environments:write";
141
+ "clients:read": "clients:read";
142
+ "clients:write": "clients:write";
143
+ "clients:rotate_secret": "clients:rotate_secret";
144
+ "connections:read": "connections:read";
145
+ "connections:write": "connections:write";
146
+ "domains:read": "domains:read";
147
+ "domains:write": "domains:write";
148
+ "users:read": "users:read";
149
+ "users:write": "users:write";
150
+ "users:block": "users:block";
151
+ "users:delete": "users:delete";
152
+ "user_identities:read": "user_identities:read";
153
+ "user_identities:write": "user_identities:write";
154
+ "user_passkeys:read": "user_passkeys:read";
155
+ "user_passkeys:write": "user_passkeys:write";
156
+ "user_sessions:read": "user_sessions:read";
157
+ "user_sessions:write": "user_sessions:write";
158
+ "user_data_jobs:read": "user_data_jobs:read";
159
+ "user_data_jobs:write": "user_data_jobs:write";
160
+ "webhooks:read": "webhooks:read";
161
+ "webhooks:write": "webhooks:write";
162
+ "webhooks:rotate_secret": "webhooks:rotate_secret";
163
+ "webhooks:test": "webhooks:test";
164
+ "audit_events:read": "audit_events:read";
165
+ "usage:read": "usage:read";
166
+ introspect: "introspect";
167
+ "billing:read": "billing:read";
168
+ "billing:write": "billing:write";
169
+ "api_keys:read": "api_keys:read";
170
+ "api_keys:write": "api_keys:write";
171
+ "impersonation:create": "impersonation:create";
172
+ }>>;
173
+ }, z.core.$strict>;
174
+ export type ImpersonationSession = z.infer<typeof impersonationSessionSchema>;
175
+ export declare const impersonationCreateResponseSchema: z.ZodObject<{
176
+ actor_user_id: z.ZodString;
177
+ impersonated_user_id: z.ZodString;
178
+ reason: z.ZodString;
179
+ started_at: z.ZodISODateTime;
180
+ expires_at: z.ZodISODateTime;
181
+ forbidden_scopes: z.ZodArray<z.ZodEnum<{
182
+ "workspaces:read": "workspaces:read";
183
+ "workspaces:write": "workspaces:write";
184
+ "workspace_members:read": "workspace_members:read";
185
+ "projects:read": "projects:read";
186
+ "projects:write": "projects:write";
187
+ "environments:read": "environments:read";
188
+ "environments:write": "environments:write";
189
+ "clients:read": "clients:read";
190
+ "clients:write": "clients:write";
191
+ "clients:rotate_secret": "clients:rotate_secret";
192
+ "connections:read": "connections:read";
193
+ "connections:write": "connections:write";
194
+ "domains:read": "domains:read";
195
+ "domains:write": "domains:write";
196
+ "users:read": "users:read";
197
+ "users:write": "users:write";
198
+ "users:block": "users:block";
199
+ "users:delete": "users:delete";
200
+ "user_identities:read": "user_identities:read";
201
+ "user_identities:write": "user_identities:write";
202
+ "user_passkeys:read": "user_passkeys:read";
203
+ "user_passkeys:write": "user_passkeys:write";
204
+ "user_sessions:read": "user_sessions:read";
205
+ "user_sessions:write": "user_sessions:write";
206
+ "user_data_jobs:read": "user_data_jobs:read";
207
+ "user_data_jobs:write": "user_data_jobs:write";
208
+ "webhooks:read": "webhooks:read";
209
+ "webhooks:write": "webhooks:write";
210
+ "webhooks:rotate_secret": "webhooks:rotate_secret";
211
+ "webhooks:test": "webhooks:test";
212
+ "audit_events:read": "audit_events:read";
213
+ "usage:read": "usage:read";
214
+ introspect: "introspect";
215
+ "billing:read": "billing:read";
216
+ "billing:write": "billing:write";
217
+ "api_keys:read": "api_keys:read";
218
+ "api_keys:write": "api_keys:write";
219
+ "impersonation:create": "impersonation:create";
220
+ }>>;
221
+ }, z.core.$strict>;
222
+ export type ImpersonationCreateResponse = z.infer<typeof impersonationCreateResponseSchema>;
package/dist/rbac.js ADDED
@@ -0,0 +1,226 @@
1
+ import { z } from "zod";
2
+ import { userIdSchema } from "./primitives.js";
3
+ /**
4
+ * Dashboard / Management API RBAC (design.md §27.2's role table, §11.2
5
+ * `workspace_members.role`).
6
+ */
7
+ export const WORKSPACE_ROLES = [
8
+ "owner",
9
+ "admin",
10
+ "developer",
11
+ "support",
12
+ "billing",
13
+ "viewer",
14
+ ];
15
+ export const workspaceRoleSchema = z.enum(WORKSPACE_ROLES);
16
+ // ---------------------------------------------------------------------------
17
+ // Scopes (design.md §26.1: "scope最小化" — Management API keys are granted a
18
+ // minimal explicit scope list, not a raw role)
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * The full set of grantable Management API scopes. Most use the
22
+ * `<resource>:<action>` form; protocol capabilities such as `introspect` are
23
+ * standalone. This is the declarative permission vocabulary both Management
24
+ * API keys (design.md §11.12) and dashboard roles (design.md §27.2) use.
25
+ */
26
+ export const MANAGEMENT_SCOPES = [
27
+ "workspaces:read",
28
+ "workspaces:write",
29
+ // `GET /workspaces/:workspaceId/members` (design.md §11.2, §27.3's
30
+ // Security settings screen, §27.2's RBAC table). See the `ROLE_SCOPES`
31
+ // doc comment below for which roles are granted this.
32
+ "workspace_members:read",
33
+ "projects:read",
34
+ "projects:write",
35
+ "environments:read",
36
+ "environments:write",
37
+ "clients:read",
38
+ "clients:write",
39
+ "clients:rotate_secret",
40
+ "connections:read",
41
+ "connections:write",
42
+ "domains:read",
43
+ "domains:write",
44
+ "users:read",
45
+ "users:write",
46
+ "users:block",
47
+ "users:delete",
48
+ "user_identities:read",
49
+ "user_identities:write",
50
+ "user_passkeys:read",
51
+ "user_passkeys:write",
52
+ "user_sessions:read",
53
+ "user_sessions:write",
54
+ "user_data_jobs:read",
55
+ "user_data_jobs:write",
56
+ "webhooks:read",
57
+ "webhooks:write",
58
+ "webhooks:rotate_secret",
59
+ "webhooks:test",
60
+ "audit_events:read",
61
+ "usage:read",
62
+ // Scoped Management API key permission for POST /oauth2/introspect
63
+ // (design.md §15.8); not a resource CRUD scope.
64
+ "introspect",
65
+ "billing:read",
66
+ "billing:write",
67
+ "api_keys:read",
68
+ "api_keys:write",
69
+ "impersonation:create",
70
+ ];
71
+ export const managementScopeSchema = z.enum(MANAGEMENT_SCOPES);
72
+ /**
73
+ * Scopes that let an actor change how a user authenticates: linking/unlinking
74
+ * a social identity or adding/removing a passkey (design.md §12.3/§12.5,
75
+ * §25's "credential"). Deliberately narrower than "anything about the user
76
+ * account" — e.g. blocking a user or editing their display name is an
77
+ * account-state/profile change, not a credential change.
78
+ *
79
+ * design.md §25: "support roleだけではcredentialを変更できない." §27.4 forbids
80
+ * the same category of action during impersonation ("credential変更...は禁止").
81
+ */
82
+ export const CREDENTIAL_MUTATING_SCOPES = [
83
+ "user_identities:write",
84
+ "user_passkeys:write",
85
+ ];
86
+ /** design.md §27.4: impersonation additionally forbids billing and API key operations. */
87
+ export const IMPERSONATION_FORBIDDEN_SCOPES = [
88
+ ...CREDENTIAL_MUTATING_SCOPES,
89
+ "billing:read",
90
+ "billing:write",
91
+ "api_keys:read",
92
+ "api_keys:write",
93
+ ];
94
+ /**
95
+ * design.md §27.2 role → permission table:
96
+ *
97
+ * | Role | 権限 |
98
+ * |-----------|------|
99
+ * | Owner | 全操作、課金、Workspace削除 |
100
+ * | Admin | Project、Environment、ユーザー管理 |
101
+ * | Developer | Client、Connection、Domain、Webhook |
102
+ * | Support | ユーザー閲覧、session失効 |
103
+ * | Billing | 課金・使用量 |
104
+ * | Viewer | 読み取りのみ |
105
+ *
106
+ * `workspace_members:read` grant decision (no dedicated row in the table
107
+ * above — the assignment that added `GET /workspaces/:workspaceId/members`
108
+ * requires a defensible reading of it): granted to owner/admin/support/
109
+ * billing/viewer, withheld from developer. The Developer table lists "Client,
110
+ * Connection, Domain, Webhook" resources, with `introspect` as a standalone
111
+ * OAuth capability for resource-server token validation. The test below
112
+ * ensures the developer role gets no other resource prefixes. Every other
113
+ * role either reads broadly (`viewer`, "読み取りのみ") or needs the roster for
114
+ * its work (`admin` administers the workspace; `support`/`billing` deal with
115
+ * the workspace's people and billing contacts day to day).
116
+ */
117
+ export const ROLE_SCOPES = {
118
+ owner: MANAGEMENT_SCOPES,
119
+ admin: [
120
+ "workspaces:read",
121
+ "workspace_members:read",
122
+ "projects:read",
123
+ "projects:write",
124
+ "environments:read",
125
+ "environments:write",
126
+ "introspect",
127
+ "users:read",
128
+ "users:write",
129
+ "users:block",
130
+ "users:delete",
131
+ "user_identities:read",
132
+ "user_identities:write",
133
+ "user_passkeys:read",
134
+ "user_passkeys:write",
135
+ "user_sessions:read",
136
+ "user_sessions:write",
137
+ "user_data_jobs:read",
138
+ "user_data_jobs:write",
139
+ "audit_events:read",
140
+ "impersonation:create",
141
+ ],
142
+ developer: [
143
+ "clients:read",
144
+ "introspect",
145
+ "clients:write",
146
+ "clients:rotate_secret",
147
+ "connections:read",
148
+ "connections:write",
149
+ "domains:read",
150
+ "domains:write",
151
+ "webhooks:read",
152
+ "webhooks:write",
153
+ "webhooks:rotate_secret",
154
+ "webhooks:test",
155
+ ],
156
+ support: [
157
+ "users:read",
158
+ "user_identities:read",
159
+ "user_passkeys:read",
160
+ "user_sessions:read",
161
+ "user_sessions:write",
162
+ "workspace_members:read",
163
+ ],
164
+ billing: [
165
+ "billing:read",
166
+ "billing:write",
167
+ "usage:read",
168
+ "workspaces:read",
169
+ "workspace_members:read",
170
+ ],
171
+ viewer: [
172
+ "workspaces:read",
173
+ "workspace_members:read",
174
+ "projects:read",
175
+ "environments:read",
176
+ "clients:read",
177
+ "connections:read",
178
+ "domains:read",
179
+ "users:read",
180
+ "user_identities:read",
181
+ "user_passkeys:read",
182
+ "user_sessions:read",
183
+ "user_data_jobs:read",
184
+ "webhooks:read",
185
+ "audit_events:read",
186
+ "usage:read",
187
+ "billing:read",
188
+ "api_keys:read",
189
+ ],
190
+ };
191
+ export const scopesForRole = (role) => ROLE_SCOPES[role];
192
+ export const roleHasScope = (role, scope) => ROLE_SCOPES[role].includes(scope);
193
+ /** A scope is read-only when it grants inspection without changing a resource or token state. */
194
+ export const isReadOnlyScope = (scope) => scope === "introspect" || scope.endsWith(":read");
195
+ // ---------------------------------------------------------------------------
196
+ // Impersonation (design.md §27.4)
197
+ // ---------------------------------------------------------------------------
198
+ /** design.md §27.4: "OwnerまたはAdmin" may start an impersonation session. */
199
+ export const IMPERSONATION_ALLOWED_ROLES = [
200
+ "owner",
201
+ "admin",
202
+ ];
203
+ export const impersonationAllowedRoleSchema = z.enum(IMPERSONATION_ALLOWED_ROLES);
204
+ /** design.md §27.4: "最大15分". */
205
+ export const IMPERSONATION_MAX_DURATION_MINUTES = 15;
206
+ /** design.md §27.4: "理由入力" is a required, non-empty justification. */
207
+ export const impersonationReasonSchema = z.string().min(10).max(1000);
208
+ export const impersonationCreateRequestSchema = z.strictObject({
209
+ user_id: userIdSchema,
210
+ reason: impersonationReasonSchema,
211
+ duration_minutes: z.number().int().min(1).max(IMPERSONATION_MAX_DURATION_MINUTES),
212
+ });
213
+ /**
214
+ * design.md §27.4: "UIに常時banner", "全操作をactorとimpersonated userの両方で
215
+ * 監査". The response carries both identities so the dashboard can render the
216
+ * mandatory banner and so every subsequent action can be dual-audited.
217
+ */
218
+ export const impersonationSessionSchema = z.strictObject({
219
+ actor_user_id: userIdSchema,
220
+ impersonated_user_id: userIdSchema,
221
+ reason: impersonationReasonSchema,
222
+ started_at: z.iso.datetime(),
223
+ expires_at: z.iso.datetime(),
224
+ forbidden_scopes: z.array(managementScopeSchema),
225
+ });
226
+ export const impersonationCreateResponseSchema = impersonationSessionSchema;
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `GET /usage/mau` (design.md §28: MAU課金). No D1 table is projected 1:1
4
+ * here — `mau_month` (§12.10) is a per-user ledger row, while this route
5
+ * reports the aggregated-per-workspace view design.md §28.5 describes:
6
+ * the free tier limit, threshold notifications, and grace period state.
7
+ */
8
+ export declare const MAU_FREE_TIER_LIMIT = 30000;
9
+ /** design.md §28.5: "80%、95%、100%到達時にOwner/Billing roleへ通知". */
10
+ export declare const MAU_THRESHOLD_LEVELS: readonly [80, 95, 100];
11
+ export declare const mauThresholdLevelSchema: z.ZodUnion<readonly [z.ZodLiteral<80>, z.ZodLiteral<95>, z.ZodLiteral<100>]>;
12
+ export type MauThresholdLevel = (typeof MAU_THRESHOLD_LEVELS)[number];
13
+ /** `billing_month` wire format: `YYYY-MM` (design.md §12.10 `mau_month.billing_month`). */
14
+ export declare const billingMonthSchema: z.ZodString;
15
+ /**
16
+ * design.md §28.5: unbilled workspaces get a 72-hour grace period at 30,000
17
+ * MAU; existing users keep logging in throughout, but if billing is not
18
+ * activated before it expires, only new-user creation is blocked.
19
+ */
20
+ export declare const GRACE_PERIOD_STATUSES: readonly ["none", "active", "expired"];
21
+ export declare const gracePeriodStatusSchema: z.ZodEnum<{
22
+ expired: "expired";
23
+ none: "none";
24
+ active: "active";
25
+ }>;
26
+ export type GracePeriodStatus = (typeof GRACE_PERIOD_STATUSES)[number];
27
+ export declare const gracePeriodSchema: z.ZodObject<{
28
+ status: z.ZodEnum<{
29
+ expired: "expired";
30
+ none: "none";
31
+ active: "active";
32
+ }>;
33
+ started_at: z.ZodNullable<z.ZodISODateTime>;
34
+ expires_at: z.ZodNullable<z.ZodISODateTime>;
35
+ new_user_creation_blocked: z.ZodBoolean;
36
+ }, z.core.$strict>;
37
+ export type GracePeriod = z.infer<typeof gracePeriodSchema>;
38
+ declare const mauEnvironmentBreakdownSchema: z.ZodObject<{
39
+ environment_id: z.ZodString;
40
+ count: z.ZodNumber;
41
+ }, z.core.$strict>;
42
+ export type MauEnvironmentBreakdown = z.infer<typeof mauEnvironmentBreakdownSchema>;
43
+ export declare const mauUsageResponseSchema: z.ZodObject<{
44
+ workspace_id: z.ZodString;
45
+ billing_month: z.ZodString;
46
+ total_count: z.ZodNumber;
47
+ free_tier_limit: z.ZodLiteral<30000>;
48
+ percent_used: z.ZodNumber;
49
+ threshold_reached: z.ZodNullable<z.ZodUnion<readonly [z.ZodLiteral<80>, z.ZodLiteral<95>, z.ZodLiteral<100>]>>;
50
+ billing_activated: z.ZodBoolean;
51
+ grace_period: z.ZodObject<{
52
+ status: z.ZodEnum<{
53
+ expired: "expired";
54
+ none: "none";
55
+ active: "active";
56
+ }>;
57
+ started_at: z.ZodNullable<z.ZodISODateTime>;
58
+ expires_at: z.ZodNullable<z.ZodISODateTime>;
59
+ new_user_creation_blocked: z.ZodBoolean;
60
+ }, z.core.$strict>;
61
+ environments: z.ZodArray<z.ZodObject<{
62
+ environment_id: z.ZodString;
63
+ count: z.ZodNumber;
64
+ }, z.core.$strict>>;
65
+ }, z.core.$strict>;
66
+ export type MauUsageResponse = z.infer<typeof mauUsageResponseSchema>;
67
+ export declare const mauUsageQuerySchema: z.ZodObject<{
68
+ billing_month: z.ZodOptional<z.ZodString>;
69
+ environment_id: z.ZodOptional<z.ZodString>;
70
+ }, z.core.$strip>;
71
+ export type MauUsageQuery = z.infer<typeof mauUsageQuerySchema>;
72
+ export {};
package/dist/usage.js ADDED
@@ -0,0 +1,52 @@
1
+ import { z } from "zod";
2
+ import { environmentIdSchema, workspaceIdSchema } from "./primitives.js";
3
+ /**
4
+ * `GET /usage/mau` (design.md §28: MAU課金). No D1 table is projected 1:1
5
+ * here — `mau_month` (§12.10) is a per-user ledger row, while this route
6
+ * reports the aggregated-per-workspace view design.md §28.5 describes:
7
+ * the free tier limit, threshold notifications, and grace period state.
8
+ */
9
+ export const MAU_FREE_TIER_LIMIT = 30_000;
10
+ /** design.md §28.5: "80%、95%、100%到達時にOwner/Billing roleへ通知". */
11
+ export const MAU_THRESHOLD_LEVELS = [80, 95, 100];
12
+ export const mauThresholdLevelSchema = z.union([z.literal(80), z.literal(95), z.literal(100)]);
13
+ /** `billing_month` wire format: `YYYY-MM` (design.md §12.10 `mau_month.billing_month`). */
14
+ export const billingMonthSchema = z.string().regex(/^\d{4}-(?:0[1-9]|1[0-2])$/);
15
+ /**
16
+ * design.md §28.5: unbilled workspaces get a 72-hour grace period at 30,000
17
+ * MAU; existing users keep logging in throughout, but if billing is not
18
+ * activated before it expires, only new-user creation is blocked.
19
+ */
20
+ export const GRACE_PERIOD_STATUSES = ["none", "active", "expired"];
21
+ export const gracePeriodStatusSchema = z.enum(GRACE_PERIOD_STATUSES);
22
+ export const gracePeriodSchema = z.strictObject({
23
+ status: gracePeriodStatusSchema,
24
+ started_at: z.iso.datetime().nullable(),
25
+ /** design.md §28.5: "72時間のgrace period". */
26
+ expires_at: z.iso.datetime().nullable(),
27
+ /** design.md §28.5: "新規ユーザー作成だけを停止する" once the grace period lapses unbilled. */
28
+ new_user_creation_blocked: z.boolean(),
29
+ });
30
+ const mauEnvironmentBreakdownSchema = z.strictObject({
31
+ environment_id: environmentIdSchema,
32
+ count: z.number().int().nonnegative(),
33
+ });
34
+ export const mauUsageResponseSchema = z.strictObject({
35
+ workspace_id: workspaceIdSchema,
36
+ billing_month: billingMonthSchema,
37
+ total_count: z.number().int().nonnegative(),
38
+ free_tier_limit: z.literal(MAU_FREE_TIER_LIMIT),
39
+ percent_used: z.number().nonnegative(),
40
+ /** Highest threshold level reached so far this billing month, or `null` if none. */
41
+ threshold_reached: mauThresholdLevelSchema.nullable(),
42
+ /** design.md §28.5: whether Stripe Customer/Subscription/Payment Method are active. */
43
+ billing_activated: z.boolean(),
44
+ grace_period: gracePeriodSchema,
45
+ environments: z.array(mauEnvironmentBreakdownSchema),
46
+ });
47
+ export const mauUsageQuerySchema = z.object({
48
+ /** Defaults server-side to the current billing month when omitted. */
49
+ billing_month: billingMonthSchema.optional(),
50
+ /** Narrows `environments` to a single environment (the top-level totals still reflect the whole workspace). */
51
+ environment_id: environmentIdSchema.optional(),
52
+ });