@b1-road/types 0.1.0-alpha.0 → 0.1.0-alpha.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.
- package/README.md +10 -5
- package/dist/iam.cjs.map +1 -1
- package/dist/iam.d.cts +0 -2
- package/dist/iam.d.ts +0 -2
- package/dist/index.cjs +15 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -18
- package/dist/index.d.ts +108 -18
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/package.json +17 -5
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ Ships dual ESM/CJS builds with type declarations. Zero runtime dependencies.
|
|
|
27
27
|
| Entities | The resource shapes returned on the wire (business units, members, roles, permissions, …). |
|
|
28
28
|
| Inputs | The request-body shapes the API accepts. |
|
|
29
29
|
| Permissions | The `action:subject` permission algebra and its constants. |
|
|
30
|
+
| Webhooks | Webhook event types, per-event payloads, and the delivery envelope (`RoadWebhookEvent`, `RoadWebhookPayloads`, `ROAD_WEBHOOK_EVENT_TYPES`). |
|
|
30
31
|
| `@b1-road/types/iam` | IAM control-plane types (scopes, assignments, authorization, sessions). |
|
|
31
32
|
|
|
32
33
|
```ts
|
|
@@ -36,13 +37,17 @@ const baseUrl = `${ROAD_API_URLS.production}/api/${ROAD_API_CONTRACT}`;
|
|
|
36
37
|
// → https://api.road.app/api/alpha
|
|
37
38
|
```
|
|
38
39
|
|
|
39
|
-
##
|
|
40
|
+
## A contract package — the API is a consumer too
|
|
40
41
|
|
|
41
42
|
Every wire type, permission constant, and hosted URL has exactly one definition.
|
|
42
|
-
SDKs import them; they never re-declare.
|
|
43
|
-
|
|
44
|
-
the
|
|
45
|
-
|
|
43
|
+
SDKs import them; they never re-declare. **The Road API depends on this package
|
|
44
|
+
as well** — not as "an SDK the API consumes," but as the contract both sides
|
|
45
|
+
agree on: the API (the producer) declares the wire shapes here and conforms its
|
|
46
|
+
DTOs to them, while the SDKs (the consumers) read the same shapes. The dependency
|
|
47
|
+
direction `API → @b1-road/types` is correct and intended. If a binding or the API
|
|
48
|
+
needs a shape this package doesn't yet expose, it contributes the shape back here
|
|
49
|
+
in the same change — so the API, React, Nest, and Laravel definitions can never
|
|
50
|
+
drift. This is the load-bearing principle of the ecosystem.
|
|
46
51
|
|
|
47
52
|
## Versioning
|
|
48
53
|
|
package/dist/iam.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/iam.ts"],"sourcesContent":["/**\n * IAM control-plane wire types. These describe the shapes Road's IAM API\n * speaks: scopes, assignments, authorization checks, effective permissions,\n * token exchange, and sessions.\n *\n * They live behind a subpath (`@b1-road/types/iam`) so the React SDK — which\n * never needs the control-plane — doesn't pay for them in its tree-shaken\n * bundle. The Nest SDK imports from here directly.\n */\n\nimport type { RoadPermission } from \"./permissions\";\n\n/** Scope shape. Three flavors today; platforms may register more over time. */\nexport type ScopeType = \"system\" | \"business_unit\" | \"platform\";\n\n/** Subjects the IAM engine can authorize. `service` covers M2M; `api_key` is legacy. */\nexport type SubjectType = \"user\" | \"service\" | \"api_key\";\n\nexport interface Scope {\n id: string;\n type: ScopeType;\n externalId: string | null;\n parentScopeId: string | null;\n parentScope?: {\n id: string;\n type: ScopeType;\n externalId: string | null;\n } | null;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt?: string;\n}\n\nexport interface CreateScopeInput {\n type: ScopeType;\n externalId?: string | null;\n parentScopeId?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Assignment {\n id: string;\n subjectType: SubjectType;\n subjectId: string;\n roleId: string;\n scopeId: string;\n grantedBy: string;\n grantedAt: string;\n expiresAt: string | null;\n}\n\nexport interface CreateAssignmentInput {\n subjectType: SubjectType;\n subjectId: string;\n roleId: string;\n scopeId: string;\n expiresAt?: string | null;\n}\n\nexport interface AuthorizeInput {\n subjectType: SubjectType;\n subjectId: string;\n scopeId: string;\n /** Either a single permission string (`\"read:Member\"`) or the wildcard. */\n permission: RoadPermission | (string & {});\n}\n\nexport interface AuthorizeResult {\n allowed: boolean;\n reason: string;\n
|
|
1
|
+
{"version":3,"sources":["../src/iam.ts"],"sourcesContent":["/**\n * IAM control-plane wire types. These describe the shapes Road's IAM API\n * speaks: scopes, assignments, authorization checks, effective permissions,\n * token exchange, and sessions.\n *\n * They live behind a subpath (`@b1-road/types/iam`) so the React SDK — which\n * never needs the control-plane — doesn't pay for them in its tree-shaken\n * bundle. The Nest SDK imports from here directly.\n */\n\nimport type { RoadPermission } from \"./permissions\";\n\n/** Scope shape. Three flavors today; platforms may register more over time. */\nexport type ScopeType = \"system\" | \"business_unit\" | \"platform\";\n\n/** Subjects the IAM engine can authorize. `service` covers M2M; `api_key` is legacy. */\nexport type SubjectType = \"user\" | \"service\" | \"api_key\";\n\nexport interface Scope {\n id: string;\n type: ScopeType;\n externalId: string | null;\n parentScopeId: string | null;\n parentScope?: {\n id: string;\n type: ScopeType;\n externalId: string | null;\n } | null;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt?: string;\n}\n\nexport interface CreateScopeInput {\n type: ScopeType;\n externalId?: string | null;\n parentScopeId?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Assignment {\n id: string;\n subjectType: SubjectType;\n subjectId: string;\n roleId: string;\n scopeId: string;\n grantedBy: string;\n grantedAt: string;\n expiresAt: string | null;\n}\n\nexport interface CreateAssignmentInput {\n subjectType: SubjectType;\n subjectId: string;\n roleId: string;\n scopeId: string;\n expiresAt?: string | null;\n}\n\nexport interface AuthorizeInput {\n subjectType: SubjectType;\n subjectId: string;\n scopeId: string;\n /** Either a single permission string (`\"read:Member\"`) or the wildcard. */\n permission: RoadPermission | (string & {});\n}\n\nexport interface AuthorizeResult {\n allowed: boolean;\n reason: string;\n}\n\nexport interface AuthorizeBatchInput {\n subjectType: SubjectType;\n subjectId: string;\n scopeId: string;\n permissions: Array<RoadPermission | (string & {})>;\n}\n\nexport interface AuthorizeBatchResult {\n results: Array<{ permission: string; allowed: boolean }>;\n}\n\nexport interface EffectivePermissionsResult {\n /** Expanded permissions; `manage:X` has been expanded into the CRUD set. */\n permissions: string[];\n}\n\nexport interface Session {\n id: string;\n deviceName: string;\n ipAddress: string | null;\n userAgent?: string;\n provider: string;\n lastUsedAt: string;\n createdAt: string;\n current: boolean;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
package/dist/iam.d.cts
CHANGED
|
@@ -61,8 +61,6 @@ interface AuthorizeInput {
|
|
|
61
61
|
interface AuthorizeResult {
|
|
62
62
|
allowed: boolean;
|
|
63
63
|
reason: string;
|
|
64
|
-
/** Scope chain that was walked during evaluation (target → ... → root). */
|
|
65
|
-
evaluatedScopes: string[];
|
|
66
64
|
}
|
|
67
65
|
interface AuthorizeBatchInput {
|
|
68
66
|
subjectType: SubjectType;
|
package/dist/iam.d.ts
CHANGED
|
@@ -61,8 +61,6 @@ interface AuthorizeInput {
|
|
|
61
61
|
interface AuthorizeResult {
|
|
62
62
|
allowed: boolean;
|
|
63
63
|
reason: string;
|
|
64
|
-
/** Scope chain that was walked during evaluation (target → ... → root). */
|
|
65
|
-
evaluatedScopes: string[];
|
|
66
64
|
}
|
|
67
65
|
interface AuthorizeBatchInput {
|
|
68
66
|
subjectType: SubjectType;
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(src_exports, {
|
|
|
24
24
|
ROAD_API_URLS: () => ROAD_API_URLS,
|
|
25
25
|
ROAD_CORE_ACTIONS: () => ROAD_CORE_ACTIONS,
|
|
26
26
|
ROAD_CORE_SUBJECTS: () => ROAD_CORE_SUBJECTS,
|
|
27
|
+
ROAD_WEBHOOK_EVENT_TYPES: () => ROAD_WEBHOOK_EVENT_TYPES,
|
|
27
28
|
ROAD_WILDCARD_PERMISSION: () => ROAD_WILDCARD_PERMISSION
|
|
28
29
|
});
|
|
29
30
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -55,12 +56,26 @@ var ROAD_CORE_SUBJECTS = [
|
|
|
55
56
|
"Invitation"
|
|
56
57
|
];
|
|
57
58
|
var ROAD_WILDCARD_PERMISSION = "*";
|
|
59
|
+
|
|
60
|
+
// src/webhooks.ts
|
|
61
|
+
var ROAD_WEBHOOK_EVENT_TYPES = [
|
|
62
|
+
"organization.invitation.created",
|
|
63
|
+
"organization.invitation.accepted",
|
|
64
|
+
"organization.invitation.rejected",
|
|
65
|
+
"organization.invitation.cancelled",
|
|
66
|
+
"organization.member.joined",
|
|
67
|
+
"organization.member.suspended",
|
|
68
|
+
"organization.member.reinstated",
|
|
69
|
+
"organization.member.removed",
|
|
70
|
+
"organization.member.role-changed"
|
|
71
|
+
];
|
|
58
72
|
// Annotate the CommonJS export names for ESM import in node:
|
|
59
73
|
0 && (module.exports = {
|
|
60
74
|
ROAD_API_CONTRACT,
|
|
61
75
|
ROAD_API_URLS,
|
|
62
76
|
ROAD_CORE_ACTIONS,
|
|
63
77
|
ROAD_CORE_SUBJECTS,
|
|
78
|
+
ROAD_WEBHOOK_EVENT_TYPES,
|
|
64
79
|
ROAD_WILDCARD_PERMISSION
|
|
65
80
|
});
|
|
66
81
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api-contract.ts","../src/api-urls.ts","../src/permissions.ts"],"sourcesContent":["export * from \"./api-contract\";\nexport * from \"./api-urls\";\nexport * from \"./entities\";\nexport * from \"./inputs\";\nexport * from \"./permissions\";\n","/**\n * The Road API **contract version** — the major boundary of the HTTP wire\n * surface. The Road API mounts every route under `/api/<contract>`, and every\n * SDK builds its base path as `${host}/api/${ROAD_API_CONTRACT}`.\n *\n * This is the single source of truth for that value. The Road API imports it\n * for its global prefix; the in-repo clients (admin, tester) and the published\n * SDKs read it from here. It is **not** environment configuration — it is\n * identical in every environment and changes only by a deliberate edit when the\n * wire contract makes a breaking change: `alpha` → `v1` → `v2`.\n *\n * Promoting this from `alpha` to `v1` is the trigger to take the SDKs to their\n * first stable `1.0.0`. See `docs/plans/14-sdk-publishing-and-versioning.md`.\n */\nexport const ROAD_API_CONTRACT = \"alpha\" as const;\n\nexport type RoadApiContract = typeof ROAD_API_CONTRACT;\n","/**\n * Road's hosted API base URLs. SDKs default to ROAD_API_URLS.production; the\n * sandbox URL is the deployed Road sandbox (override via the SDK's apiBaseUrl\n * config if you're running against a different environment, eg. local dev or\n * a private staging cluster).\n *\n * If the deployed sandbox hostname changes, update this constant — it's the\n * single source of truth every SDK reads from.\n */\nexport const ROAD_API_URLS = {\n production: \"https://api.road.app\",\n sandbox: \"https://api.road-sandbox.b1.app\",\n} as const;\n\nexport type RoadEnvironment = keyof typeof ROAD_API_URLS;\n","/**\n * Road IAM permission algebra. Permissions are `${action}:${subject}` strings;\n * the wildcard `\"*\"` short-circuits to true for every action in a scope.\n *\n * The widget catalog calls into actions and subjects Road ships by default\n * (the union types below). Platforms can declare their own actions and\n * subjects in their IAM catalog — those flow through useCan as plain strings,\n * still type-safe via `RoadPermission | (string & {})` in the React SDK.\n */\n\n/**\n * The CRUD verbs Road's IAM engine recognizes, plus `manage` which the\n * engine expands server-side into the full CRUD set for the same subject\n * (`manage:Member` ⇒ also `create|read|update|delete:Member` in the\n * effective-permissions response).\n *\n * Platforms can register their own actions (`approve`, `submit`, `list`, …)\n * — those flow through useCan as plain strings (the `(string & {})` part\n * of PermissionInput in the React SDK), still type-safe via that escape.\n */\nexport type RoadAction = \"create\" | \"read\" | \"update\" | \"delete\" | \"manage\";\n\n/**\n * Built-in subjects Road's own permissions cover. Mirrors the subjects\n * registered in the API's `Subjects` constant\n * (apps/api/src/modules/iam/authorization/constants/subjects.ts), limited\n * to the subjects user-facing widgets actually surface:\n *\n * - BusinessUnit: system-level — create new BUs\n * - BUDashboard: BU-level — read a BU's detail page\n * - BUSettings: BU-level — edit a BU's settings\n * - Member, Role, Permission, Invitation: BU-level CRUD\n *\n * Admin / platform-engineer subjects (System, Platform, AdminUser,\n * PlatformIdentity, …) are not exposed here — they belong to a future\n * developer-facing widget (and admin SDK), not the customer-facing toolkit.\n *\n * Platform-specific subjects (eg. A4L's `Agent`) are not enumerated —\n * platforms register them at runtime under their own scope, and useCan's\n * `(string & {})` accepts them without complaint.\n */\nexport type RoadCoreSubject =\n | \"BusinessUnit\"\n | \"BUDashboard\"\n | \"BUSettings\"\n | \"Member\"\n | \"Role\"\n | \"Permission\"\n | \"Invitation\";\n\n/** `${action}:${Subject}` for the core set, plus the wildcard. */\nexport type RoadPermission = `${RoadAction}:${RoadCoreSubject}` | \"*\";\n\n/** Runtime array of the core actions — handy for iteration or validation. */\nexport const ROAD_CORE_ACTIONS = [\n \"create\",\n \"read\",\n \"update\",\n \"delete\",\n \"manage\",\n] as const satisfies readonly RoadAction[];\n\n/** Runtime array of the core subjects — handy for iteration or validation. */\nexport const ROAD_CORE_SUBJECTS = [\n \"BusinessUnit\",\n \"BUDashboard\",\n \"BUSettings\",\n \"Member\",\n \"Role\",\n \"Permission\",\n \"Invitation\",\n] as const satisfies readonly RoadCoreSubject[];\n\n/** The wildcard permission string. Use this instead of literal \"*\" for grep-ability. */\nexport const ROAD_WILDCARD_PERMISSION = \"*\" as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACcO,IAAM,oBAAoB;;;ACL1B,IAAM,gBAAgB;AAAA,EAC3B,YAAY;AAAA,EACZ,SAAS;AACX;;;AC0CO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,2BAA2B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api-contract.ts","../src/api-urls.ts","../src/permissions.ts","../src/webhooks.ts"],"sourcesContent":["export * from \"./api-contract\";\nexport * from \"./api-urls\";\nexport * from \"./entities\";\nexport * from \"./inputs\";\nexport * from \"./permissions\";\nexport * from \"./webhooks\";\n","/**\n * The Road API **contract version** — the major boundary of the HTTP wire\n * surface. The Road API mounts every route under `/api/<contract>`, and every\n * SDK builds its base path as `${host}/api/${ROAD_API_CONTRACT}`.\n *\n * This is the single source of truth for that value. The Road API imports it\n * for its global prefix; the in-repo clients (admin, tester) and the published\n * SDKs read it from here. It is **not** environment configuration — it is\n * identical in every environment and changes only by a deliberate edit when the\n * wire contract makes a breaking change: `alpha` → `v1` → `v2`.\n *\n * Promoting this from `alpha` to `v1` is the trigger to take the SDKs to their\n * first stable `1.0.0`. See `docs/plans/14-sdk-publishing-and-versioning.md`.\n */\nexport const ROAD_API_CONTRACT = \"alpha\" as const;\n\nexport type RoadApiContract = typeof ROAD_API_CONTRACT;\n","/**\n * Road's hosted API base URLs. SDKs default to ROAD_API_URLS.production; the\n * sandbox URL is the deployed Road sandbox (override via the SDK's apiBaseUrl\n * config if you're running against a different environment, eg. local dev or\n * a private staging cluster).\n *\n * If the deployed sandbox hostname changes, update this constant — it's the\n * single source of truth every SDK reads from.\n */\nexport const ROAD_API_URLS = {\n production: \"https://api.road.app\",\n sandbox: \"https://api.road-sandbox.b1.app\",\n} as const;\n\nexport type RoadEnvironment = keyof typeof ROAD_API_URLS;\n","/**\n * Road IAM permission algebra. Permissions are `${action}:${subject}` strings;\n * the wildcard `\"*\"` short-circuits to true for every action in a scope.\n *\n * The widget catalog calls into actions and subjects Road ships by default\n * (the union types below). Platforms can declare their own actions and\n * subjects in their IAM catalog — those flow through useCan as plain strings,\n * still type-safe via `RoadPermission | (string & {})` in the React SDK.\n */\n\n/**\n * The CRUD verbs Road's IAM engine recognizes, plus `manage` which the\n * engine expands server-side into the full CRUD set for the same subject\n * (`manage:Member` ⇒ also `create|read|update|delete:Member` in the\n * effective-permissions response).\n *\n * Platforms can register their own actions (`approve`, `submit`, `list`, …)\n * — those flow through useCan as plain strings (the `(string & {})` part\n * of PermissionInput in the React SDK), still type-safe via that escape.\n */\nexport type RoadAction = \"create\" | \"read\" | \"update\" | \"delete\" | \"manage\";\n\n/**\n * Built-in subjects Road's own permissions cover. Mirrors the subjects\n * registered in the API's `Subjects` constant\n * (apps/api/src/modules/iam/authorization/constants/subjects.ts), limited\n * to the subjects user-facing widgets actually surface:\n *\n * - BusinessUnit: system-level — create new BUs\n * - BUDashboard: BU-level — read a BU's detail page\n * - BUSettings: BU-level — edit a BU's settings\n * - Member, Role, Permission, Invitation: BU-level CRUD\n *\n * Admin / platform-engineer subjects (System, Platform, AdminUser,\n * PlatformIdentity, …) are not exposed here — they belong to a future\n * developer-facing widget (and admin SDK), not the customer-facing toolkit.\n *\n * Platform-specific subjects (eg. A4L's `Agent`) are not enumerated —\n * platforms register them at runtime under their own scope, and useCan's\n * `(string & {})` accepts them without complaint.\n */\nexport type RoadCoreSubject =\n | \"BusinessUnit\"\n | \"BUDashboard\"\n | \"BUSettings\"\n | \"Member\"\n | \"Role\"\n | \"Permission\"\n | \"Invitation\";\n\n/** `${action}:${Subject}` for the core set, plus the wildcard. */\nexport type RoadPermission = `${RoadAction}:${RoadCoreSubject}` | \"*\";\n\n/** Runtime array of the core actions — handy for iteration or validation. */\nexport const ROAD_CORE_ACTIONS = [\n \"create\",\n \"read\",\n \"update\",\n \"delete\",\n \"manage\",\n] as const satisfies readonly RoadAction[];\n\n/** Runtime array of the core subjects — handy for iteration or validation. */\nexport const ROAD_CORE_SUBJECTS = [\n \"BusinessUnit\",\n \"BUDashboard\",\n \"BUSettings\",\n \"Member\",\n \"Role\",\n \"Permission\",\n \"Invitation\",\n] as const satisfies readonly RoadCoreSubject[];\n\n/** The wildcard permission string. Use this instead of literal \"*\" for grep-ability. */\nexport const ROAD_WILDCARD_PERMISSION = \"*\" as const;\n","/**\n * Road webhook events — the canonical wire contract every SDK builds on.\n *\n * The event-type strings and `data` payloads mirror exactly what the Road API\n * delivers: the `event` and `data` fields of the webhook POST body, and the\n * `X-Road-Event` header. SDKs that receive webhooks import from here and never\n * redefine them (SDK DX Bar principle 11 — one source of truth).\n *\n * Only the public `organization.*` events are listed; internal/experimental\n * event namespaces are intentionally excluded from the SDK surface.\n */\n\n/** Payload for every `organization.invitation.*` event. */\nexport interface InvitationWebhookData {\n businessUnitId: string;\n invitationId: string;\n email: string;\n}\n\n/** Payload for `organization.member.{joined,suspended,reinstated,removed}`. */\nexport interface MemberWebhookData {\n businessUnitId: string;\n memberId: string;\n userId: string;\n}\n\n/** Payload for `organization.member.role-changed`. */\nexport interface MemberRoleChangedWebhookData extends MemberWebhookData {\n roleId: string;\n action: \"assigned\" | \"revoked\";\n}\n\n/** Maps each webhook event type to the shape of its `data` payload. */\nexport interface RoadWebhookPayloads {\n \"organization.invitation.created\": InvitationWebhookData;\n \"organization.invitation.accepted\": InvitationWebhookData;\n \"organization.invitation.rejected\": InvitationWebhookData;\n \"organization.invitation.cancelled\": InvitationWebhookData;\n \"organization.member.joined\": MemberWebhookData;\n \"organization.member.suspended\": MemberWebhookData;\n \"organization.member.reinstated\": MemberWebhookData;\n \"organization.member.removed\": MemberWebhookData;\n \"organization.member.role-changed\": MemberRoleChangedWebhookData;\n}\n\n/** Every webhook event type the Road API can deliver. */\nexport type RoadWebhookEventType = keyof RoadWebhookPayloads;\n\n/**\n * The exact envelope the Road API POSTs to a registered webhook URL —\n * mirrors the delivered body `{ id, event, timestamp, data }`.\n */\nexport interface RoadWebhookEvent<\n T extends RoadWebhookEventType = RoadWebhookEventType,\n> {\n /** Unique delivery id — also sent as the `X-Road-Delivery-Id` header. */\n id: string;\n /** The event type — also sent as the `X-Road-Event` header. */\n event: T;\n /** ISO-8601 timestamp of the delivery. */\n timestamp: string;\n /** Event-specific payload. */\n data: RoadWebhookPayloads[T];\n}\n\n/**\n * Runtime list of every webhook event type — handy for registering a\n * subscription to \"all events\". `satisfies` guarantees no typo'd or\n * stale entry slips in.\n */\nexport const ROAD_WEBHOOK_EVENT_TYPES = [\n \"organization.invitation.created\",\n \"organization.invitation.accepted\",\n \"organization.invitation.rejected\",\n \"organization.invitation.cancelled\",\n \"organization.member.joined\",\n \"organization.member.suspended\",\n \"organization.member.reinstated\",\n \"organization.member.removed\",\n \"organization.member.role-changed\",\n] as const satisfies readonly RoadWebhookEventType[];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACcO,IAAM,oBAAoB;;;ACL1B,IAAM,gBAAgB;AAAA,EAC3B,YAAY;AAAA,EACZ,SAAS;AACX;;;AC0CO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,2BAA2B;;;ACJjC,IAAM,2BAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -33,7 +33,7 @@ declare const ROAD_API_URLS: {
|
|
|
33
33
|
type RoadEnvironment = keyof typeof ROAD_API_URLS;
|
|
34
34
|
|
|
35
35
|
type BUStatus = "active" | "suspended" | "archived";
|
|
36
|
-
type MemberStatus = "active" | "suspended" | "
|
|
36
|
+
type MemberStatus = "active" | "suspended" | "removed";
|
|
37
37
|
interface CurrentUser {
|
|
38
38
|
id: string;
|
|
39
39
|
name: string;
|
|
@@ -96,7 +96,7 @@ interface Invitation {
|
|
|
96
96
|
email: string;
|
|
97
97
|
roleId: string;
|
|
98
98
|
roleName: string;
|
|
99
|
-
status: "pending" | "accepted" | "expired" | "cancelled";
|
|
99
|
+
status: "pending" | "accepted" | "expired" | "cancelled" | "rejected";
|
|
100
100
|
invitedAt: string;
|
|
101
101
|
expiresAt: string;
|
|
102
102
|
}
|
|
@@ -106,7 +106,9 @@ interface Role {
|
|
|
106
106
|
description: string;
|
|
107
107
|
permissions: string[];
|
|
108
108
|
isSystem: boolean;
|
|
109
|
-
|
|
109
|
+
/** Count of role assignments (users + service principals + groups). */
|
|
110
|
+
assignmentCount: number;
|
|
111
|
+
createdAt: string;
|
|
110
112
|
}
|
|
111
113
|
interface Permission {
|
|
112
114
|
id: string;
|
|
@@ -115,19 +117,42 @@ interface Permission {
|
|
|
115
117
|
description: string;
|
|
116
118
|
/** Subject group (e.g. "Member", "Role", "BusinessUnit") used to group in the picker. */
|
|
117
119
|
category: string;
|
|
120
|
+
scopeId: string;
|
|
121
|
+
createdAt: string;
|
|
118
122
|
}
|
|
119
123
|
/**
|
|
120
|
-
* Effective permissions for the current user, keyed by business-unit ID
|
|
121
|
-
*
|
|
124
|
+
* Effective permissions for the current user, keyed by business-unit ID, as the
|
|
125
|
+
* **SDK** exposes them — each grant flattened to an `"action:subject"` string
|
|
126
|
+
* (`["*"]` grants every action in that BU). This is the client-side convenience
|
|
127
|
+
* shape; the raw wire form is `ScopePermissions` / `ScopePermissionsBulk` below,
|
|
128
|
+
* which the HTTP client maps into this.
|
|
122
129
|
*/
|
|
123
130
|
type MyPermissions = Record<string, string[]>;
|
|
124
131
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
132
|
+
* A single effective-permission grant exactly as the API returns it on the
|
|
133
|
+
* wire: an `action`/`subject` pair. Wildcards are returned as-is
|
|
134
|
+
* (`{ action: "*", subject: "*" }`), not enumerated.
|
|
135
|
+
*/
|
|
136
|
+
interface PermissionTuple {
|
|
137
|
+
action: string;
|
|
138
|
+
subject: string;
|
|
139
|
+
}
|
|
140
|
+
/** Wire shape of `GET /me/permissions?scope=<scopeId>` (single scope). */
|
|
141
|
+
interface ScopePermissions {
|
|
142
|
+
permissions: PermissionTuple[];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Wire shape of `GET /me/permissions?scopes=<id>,<id>,…` — effective
|
|
146
|
+
* permissions keyed by scope id (the SDK's fan-in for multi-BU users).
|
|
147
|
+
*/
|
|
148
|
+
type ScopePermissionsBulk = Record<string, PermissionTuple[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Cursor-pagination metadata. The API issues opaque base64-url cursors the
|
|
151
|
+
* client treats as opaque — no parsing or arithmetic on the SDK side.
|
|
127
152
|
* `cursor` is null when no further page exists; `hasMore` is the canonical
|
|
128
153
|
* "more rows after this page" signal, redundant with `cursor !== null`.
|
|
129
154
|
*/
|
|
130
|
-
interface
|
|
155
|
+
interface Pagination {
|
|
131
156
|
/** Opaque cursor for the next page. Null when this is the last page. */
|
|
132
157
|
cursor: string | null;
|
|
133
158
|
/** True iff there is at least one row past this page. */
|
|
@@ -136,13 +161,15 @@ interface PageInfo {
|
|
|
136
161
|
totalCount: number;
|
|
137
162
|
}
|
|
138
163
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
164
|
+
* Canonical paged response shape for every list endpoint. Mirrors the API's
|
|
165
|
+
* universal `{ data }` envelope — the rows live under `data` (the same key
|
|
166
|
+
* as every single-resource response), with cursor `pagination` as a
|
|
167
|
+
* top-level sibling. Convertible 1:1 to React Query's useInfiniteQuery
|
|
168
|
+
* `pageParam` flow via `pagination.cursor`.
|
|
142
169
|
*/
|
|
143
170
|
interface PaginatedList<T> {
|
|
144
|
-
|
|
145
|
-
|
|
171
|
+
data: T[];
|
|
172
|
+
pagination: Pagination;
|
|
146
173
|
}
|
|
147
174
|
/**
|
|
148
175
|
* Input shape for any paginated list call. Both fields are optional —
|
|
@@ -150,7 +177,7 @@ interface PaginatedList<T> {
|
|
|
150
177
|
* (currently 20).
|
|
151
178
|
*/
|
|
152
179
|
interface PaginationInput {
|
|
153
|
-
/** Opaque cursor from a previous `
|
|
180
|
+
/** Opaque cursor from a previous response's `pagination.cursor`. Omit for the first page. */
|
|
154
181
|
cursor?: string;
|
|
155
182
|
/** Page size. Default 20, max 100 (server-enforced). */
|
|
156
183
|
limit?: number;
|
|
@@ -163,19 +190,19 @@ interface CreateBusinessUnitInput {
|
|
|
163
190
|
}
|
|
164
191
|
interface UpdateBusinessUnitInput {
|
|
165
192
|
name?: string;
|
|
166
|
-
|
|
193
|
+
joinCode?: string | null;
|
|
167
194
|
memberLimit?: number | null;
|
|
168
195
|
}
|
|
169
196
|
interface CreateRoleInput {
|
|
170
197
|
name: string;
|
|
171
|
-
description?: string;
|
|
198
|
+
description?: string | null;
|
|
172
199
|
permissions: string[];
|
|
173
200
|
/** Source role ID when "clone from existing"; informational only. */
|
|
174
201
|
cloneFromRoleId?: string;
|
|
175
202
|
}
|
|
176
203
|
interface UpdateRoleInput {
|
|
177
204
|
name?: string;
|
|
178
|
-
description?: string;
|
|
205
|
+
description?: string | null;
|
|
179
206
|
permissions?: string[];
|
|
180
207
|
}
|
|
181
208
|
interface CreateInvitationInput {
|
|
@@ -183,4 +210,67 @@ interface CreateInvitationInput {
|
|
|
183
210
|
roleId: string;
|
|
184
211
|
}
|
|
185
212
|
|
|
186
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Road webhook events — the canonical wire contract every SDK builds on.
|
|
215
|
+
*
|
|
216
|
+
* The event-type strings and `data` payloads mirror exactly what the Road API
|
|
217
|
+
* delivers: the `event` and `data` fields of the webhook POST body, and the
|
|
218
|
+
* `X-Road-Event` header. SDKs that receive webhooks import from here and never
|
|
219
|
+
* redefine them (SDK DX Bar principle 11 — one source of truth).
|
|
220
|
+
*
|
|
221
|
+
* Only the public `organization.*` events are listed; internal/experimental
|
|
222
|
+
* event namespaces are intentionally excluded from the SDK surface.
|
|
223
|
+
*/
|
|
224
|
+
/** Payload for every `organization.invitation.*` event. */
|
|
225
|
+
interface InvitationWebhookData {
|
|
226
|
+
businessUnitId: string;
|
|
227
|
+
invitationId: string;
|
|
228
|
+
email: string;
|
|
229
|
+
}
|
|
230
|
+
/** Payload for `organization.member.{joined,suspended,reinstated,removed}`. */
|
|
231
|
+
interface MemberWebhookData {
|
|
232
|
+
businessUnitId: string;
|
|
233
|
+
memberId: string;
|
|
234
|
+
userId: string;
|
|
235
|
+
}
|
|
236
|
+
/** Payload for `organization.member.role-changed`. */
|
|
237
|
+
interface MemberRoleChangedWebhookData extends MemberWebhookData {
|
|
238
|
+
roleId: string;
|
|
239
|
+
action: "assigned" | "revoked";
|
|
240
|
+
}
|
|
241
|
+
/** Maps each webhook event type to the shape of its `data` payload. */
|
|
242
|
+
interface RoadWebhookPayloads {
|
|
243
|
+
"organization.invitation.created": InvitationWebhookData;
|
|
244
|
+
"organization.invitation.accepted": InvitationWebhookData;
|
|
245
|
+
"organization.invitation.rejected": InvitationWebhookData;
|
|
246
|
+
"organization.invitation.cancelled": InvitationWebhookData;
|
|
247
|
+
"organization.member.joined": MemberWebhookData;
|
|
248
|
+
"organization.member.suspended": MemberWebhookData;
|
|
249
|
+
"organization.member.reinstated": MemberWebhookData;
|
|
250
|
+
"organization.member.removed": MemberWebhookData;
|
|
251
|
+
"organization.member.role-changed": MemberRoleChangedWebhookData;
|
|
252
|
+
}
|
|
253
|
+
/** Every webhook event type the Road API can deliver. */
|
|
254
|
+
type RoadWebhookEventType = keyof RoadWebhookPayloads;
|
|
255
|
+
/**
|
|
256
|
+
* The exact envelope the Road API POSTs to a registered webhook URL —
|
|
257
|
+
* mirrors the delivered body `{ id, event, timestamp, data }`.
|
|
258
|
+
*/
|
|
259
|
+
interface RoadWebhookEvent<T extends RoadWebhookEventType = RoadWebhookEventType> {
|
|
260
|
+
/** Unique delivery id — also sent as the `X-Road-Delivery-Id` header. */
|
|
261
|
+
id: string;
|
|
262
|
+
/** The event type — also sent as the `X-Road-Event` header. */
|
|
263
|
+
event: T;
|
|
264
|
+
/** ISO-8601 timestamp of the delivery. */
|
|
265
|
+
timestamp: string;
|
|
266
|
+
/** Event-specific payload. */
|
|
267
|
+
data: RoadWebhookPayloads[T];
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Runtime list of every webhook event type — handy for registering a
|
|
271
|
+
* subscription to "all events". `satisfies` guarantees no typo'd or
|
|
272
|
+
* stale entry slips in.
|
|
273
|
+
*/
|
|
274
|
+
declare const ROAD_WEBHOOK_EVENT_TYPES: readonly ["organization.invitation.created", "organization.invitation.accepted", "organization.invitation.rejected", "organization.invitation.cancelled", "organization.member.joined", "organization.member.suspended", "organization.member.reinstated", "organization.member.removed", "organization.member.role-changed"];
|
|
275
|
+
|
|
276
|
+
export { type BUStatus, type BusinessUnitDetail, type BusinessUnitSummary, type CreateBusinessUnitInput, type CreateInvitationInput, type CreateRoleInput, type CurrentUser, type Invitation, type InvitationWebhookData, type Member, type MemberRoleChangedWebhookData, type MemberStatus, type MemberWebhookData, type Membership, type MyBusinessUnits, type MyPermissions, type PaginatedList, type Pagination, type PaginationInput, type PendingInvitation, type Permission, type PermissionTuple, ROAD_API_CONTRACT, ROAD_API_URLS, ROAD_WEBHOOK_EVENT_TYPES, type RoadApiContract, type RoadEnvironment, type RoadWebhookEvent, type RoadWebhookEventType, type RoadWebhookPayloads, type Role, type RoleRef, type ScopePermissions, type ScopePermissionsBulk, type UpdateBusinessUnitInput, type UpdateRoleInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ declare const ROAD_API_URLS: {
|
|
|
33
33
|
type RoadEnvironment = keyof typeof ROAD_API_URLS;
|
|
34
34
|
|
|
35
35
|
type BUStatus = "active" | "suspended" | "archived";
|
|
36
|
-
type MemberStatus = "active" | "suspended" | "
|
|
36
|
+
type MemberStatus = "active" | "suspended" | "removed";
|
|
37
37
|
interface CurrentUser {
|
|
38
38
|
id: string;
|
|
39
39
|
name: string;
|
|
@@ -96,7 +96,7 @@ interface Invitation {
|
|
|
96
96
|
email: string;
|
|
97
97
|
roleId: string;
|
|
98
98
|
roleName: string;
|
|
99
|
-
status: "pending" | "accepted" | "expired" | "cancelled";
|
|
99
|
+
status: "pending" | "accepted" | "expired" | "cancelled" | "rejected";
|
|
100
100
|
invitedAt: string;
|
|
101
101
|
expiresAt: string;
|
|
102
102
|
}
|
|
@@ -106,7 +106,9 @@ interface Role {
|
|
|
106
106
|
description: string;
|
|
107
107
|
permissions: string[];
|
|
108
108
|
isSystem: boolean;
|
|
109
|
-
|
|
109
|
+
/** Count of role assignments (users + service principals + groups). */
|
|
110
|
+
assignmentCount: number;
|
|
111
|
+
createdAt: string;
|
|
110
112
|
}
|
|
111
113
|
interface Permission {
|
|
112
114
|
id: string;
|
|
@@ -115,19 +117,42 @@ interface Permission {
|
|
|
115
117
|
description: string;
|
|
116
118
|
/** Subject group (e.g. "Member", "Role", "BusinessUnit") used to group in the picker. */
|
|
117
119
|
category: string;
|
|
120
|
+
scopeId: string;
|
|
121
|
+
createdAt: string;
|
|
118
122
|
}
|
|
119
123
|
/**
|
|
120
|
-
* Effective permissions for the current user, keyed by business-unit ID
|
|
121
|
-
*
|
|
124
|
+
* Effective permissions for the current user, keyed by business-unit ID, as the
|
|
125
|
+
* **SDK** exposes them — each grant flattened to an `"action:subject"` string
|
|
126
|
+
* (`["*"]` grants every action in that BU). This is the client-side convenience
|
|
127
|
+
* shape; the raw wire form is `ScopePermissions` / `ScopePermissionsBulk` below,
|
|
128
|
+
* which the HTTP client maps into this.
|
|
122
129
|
*/
|
|
123
130
|
type MyPermissions = Record<string, string[]>;
|
|
124
131
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
132
|
+
* A single effective-permission grant exactly as the API returns it on the
|
|
133
|
+
* wire: an `action`/`subject` pair. Wildcards are returned as-is
|
|
134
|
+
* (`{ action: "*", subject: "*" }`), not enumerated.
|
|
135
|
+
*/
|
|
136
|
+
interface PermissionTuple {
|
|
137
|
+
action: string;
|
|
138
|
+
subject: string;
|
|
139
|
+
}
|
|
140
|
+
/** Wire shape of `GET /me/permissions?scope=<scopeId>` (single scope). */
|
|
141
|
+
interface ScopePermissions {
|
|
142
|
+
permissions: PermissionTuple[];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Wire shape of `GET /me/permissions?scopes=<id>,<id>,…` — effective
|
|
146
|
+
* permissions keyed by scope id (the SDK's fan-in for multi-BU users).
|
|
147
|
+
*/
|
|
148
|
+
type ScopePermissionsBulk = Record<string, PermissionTuple[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Cursor-pagination metadata. The API issues opaque base64-url cursors the
|
|
151
|
+
* client treats as opaque — no parsing or arithmetic on the SDK side.
|
|
127
152
|
* `cursor` is null when no further page exists; `hasMore` is the canonical
|
|
128
153
|
* "more rows after this page" signal, redundant with `cursor !== null`.
|
|
129
154
|
*/
|
|
130
|
-
interface
|
|
155
|
+
interface Pagination {
|
|
131
156
|
/** Opaque cursor for the next page. Null when this is the last page. */
|
|
132
157
|
cursor: string | null;
|
|
133
158
|
/** True iff there is at least one row past this page. */
|
|
@@ -136,13 +161,15 @@ interface PageInfo {
|
|
|
136
161
|
totalCount: number;
|
|
137
162
|
}
|
|
138
163
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
164
|
+
* Canonical paged response shape for every list endpoint. Mirrors the API's
|
|
165
|
+
* universal `{ data }` envelope — the rows live under `data` (the same key
|
|
166
|
+
* as every single-resource response), with cursor `pagination` as a
|
|
167
|
+
* top-level sibling. Convertible 1:1 to React Query's useInfiniteQuery
|
|
168
|
+
* `pageParam` flow via `pagination.cursor`.
|
|
142
169
|
*/
|
|
143
170
|
interface PaginatedList<T> {
|
|
144
|
-
|
|
145
|
-
|
|
171
|
+
data: T[];
|
|
172
|
+
pagination: Pagination;
|
|
146
173
|
}
|
|
147
174
|
/**
|
|
148
175
|
* Input shape for any paginated list call. Both fields are optional —
|
|
@@ -150,7 +177,7 @@ interface PaginatedList<T> {
|
|
|
150
177
|
* (currently 20).
|
|
151
178
|
*/
|
|
152
179
|
interface PaginationInput {
|
|
153
|
-
/** Opaque cursor from a previous `
|
|
180
|
+
/** Opaque cursor from a previous response's `pagination.cursor`. Omit for the first page. */
|
|
154
181
|
cursor?: string;
|
|
155
182
|
/** Page size. Default 20, max 100 (server-enforced). */
|
|
156
183
|
limit?: number;
|
|
@@ -163,19 +190,19 @@ interface CreateBusinessUnitInput {
|
|
|
163
190
|
}
|
|
164
191
|
interface UpdateBusinessUnitInput {
|
|
165
192
|
name?: string;
|
|
166
|
-
|
|
193
|
+
joinCode?: string | null;
|
|
167
194
|
memberLimit?: number | null;
|
|
168
195
|
}
|
|
169
196
|
interface CreateRoleInput {
|
|
170
197
|
name: string;
|
|
171
|
-
description?: string;
|
|
198
|
+
description?: string | null;
|
|
172
199
|
permissions: string[];
|
|
173
200
|
/** Source role ID when "clone from existing"; informational only. */
|
|
174
201
|
cloneFromRoleId?: string;
|
|
175
202
|
}
|
|
176
203
|
interface UpdateRoleInput {
|
|
177
204
|
name?: string;
|
|
178
|
-
description?: string;
|
|
205
|
+
description?: string | null;
|
|
179
206
|
permissions?: string[];
|
|
180
207
|
}
|
|
181
208
|
interface CreateInvitationInput {
|
|
@@ -183,4 +210,67 @@ interface CreateInvitationInput {
|
|
|
183
210
|
roleId: string;
|
|
184
211
|
}
|
|
185
212
|
|
|
186
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Road webhook events — the canonical wire contract every SDK builds on.
|
|
215
|
+
*
|
|
216
|
+
* The event-type strings and `data` payloads mirror exactly what the Road API
|
|
217
|
+
* delivers: the `event` and `data` fields of the webhook POST body, and the
|
|
218
|
+
* `X-Road-Event` header. SDKs that receive webhooks import from here and never
|
|
219
|
+
* redefine them (SDK DX Bar principle 11 — one source of truth).
|
|
220
|
+
*
|
|
221
|
+
* Only the public `organization.*` events are listed; internal/experimental
|
|
222
|
+
* event namespaces are intentionally excluded from the SDK surface.
|
|
223
|
+
*/
|
|
224
|
+
/** Payload for every `organization.invitation.*` event. */
|
|
225
|
+
interface InvitationWebhookData {
|
|
226
|
+
businessUnitId: string;
|
|
227
|
+
invitationId: string;
|
|
228
|
+
email: string;
|
|
229
|
+
}
|
|
230
|
+
/** Payload for `organization.member.{joined,suspended,reinstated,removed}`. */
|
|
231
|
+
interface MemberWebhookData {
|
|
232
|
+
businessUnitId: string;
|
|
233
|
+
memberId: string;
|
|
234
|
+
userId: string;
|
|
235
|
+
}
|
|
236
|
+
/** Payload for `organization.member.role-changed`. */
|
|
237
|
+
interface MemberRoleChangedWebhookData extends MemberWebhookData {
|
|
238
|
+
roleId: string;
|
|
239
|
+
action: "assigned" | "revoked";
|
|
240
|
+
}
|
|
241
|
+
/** Maps each webhook event type to the shape of its `data` payload. */
|
|
242
|
+
interface RoadWebhookPayloads {
|
|
243
|
+
"organization.invitation.created": InvitationWebhookData;
|
|
244
|
+
"organization.invitation.accepted": InvitationWebhookData;
|
|
245
|
+
"organization.invitation.rejected": InvitationWebhookData;
|
|
246
|
+
"organization.invitation.cancelled": InvitationWebhookData;
|
|
247
|
+
"organization.member.joined": MemberWebhookData;
|
|
248
|
+
"organization.member.suspended": MemberWebhookData;
|
|
249
|
+
"organization.member.reinstated": MemberWebhookData;
|
|
250
|
+
"organization.member.removed": MemberWebhookData;
|
|
251
|
+
"organization.member.role-changed": MemberRoleChangedWebhookData;
|
|
252
|
+
}
|
|
253
|
+
/** Every webhook event type the Road API can deliver. */
|
|
254
|
+
type RoadWebhookEventType = keyof RoadWebhookPayloads;
|
|
255
|
+
/**
|
|
256
|
+
* The exact envelope the Road API POSTs to a registered webhook URL —
|
|
257
|
+
* mirrors the delivered body `{ id, event, timestamp, data }`.
|
|
258
|
+
*/
|
|
259
|
+
interface RoadWebhookEvent<T extends RoadWebhookEventType = RoadWebhookEventType> {
|
|
260
|
+
/** Unique delivery id — also sent as the `X-Road-Delivery-Id` header. */
|
|
261
|
+
id: string;
|
|
262
|
+
/** The event type — also sent as the `X-Road-Event` header. */
|
|
263
|
+
event: T;
|
|
264
|
+
/** ISO-8601 timestamp of the delivery. */
|
|
265
|
+
timestamp: string;
|
|
266
|
+
/** Event-specific payload. */
|
|
267
|
+
data: RoadWebhookPayloads[T];
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Runtime list of every webhook event type — handy for registering a
|
|
271
|
+
* subscription to "all events". `satisfies` guarantees no typo'd or
|
|
272
|
+
* stale entry slips in.
|
|
273
|
+
*/
|
|
274
|
+
declare const ROAD_WEBHOOK_EVENT_TYPES: readonly ["organization.invitation.created", "organization.invitation.accepted", "organization.invitation.rejected", "organization.invitation.cancelled", "organization.member.joined", "organization.member.suspended", "organization.member.reinstated", "organization.member.removed", "organization.member.role-changed"];
|
|
275
|
+
|
|
276
|
+
export { type BUStatus, type BusinessUnitDetail, type BusinessUnitSummary, type CreateBusinessUnitInput, type CreateInvitationInput, type CreateRoleInput, type CurrentUser, type Invitation, type InvitationWebhookData, type Member, type MemberRoleChangedWebhookData, type MemberStatus, type MemberWebhookData, type Membership, type MyBusinessUnits, type MyPermissions, type PaginatedList, type Pagination, type PaginationInput, type PendingInvitation, type Permission, type PermissionTuple, ROAD_API_CONTRACT, ROAD_API_URLS, ROAD_WEBHOOK_EVENT_TYPES, type RoadApiContract, type RoadEnvironment, type RoadWebhookEvent, type RoadWebhookEventType, type RoadWebhookPayloads, type Role, type RoleRef, type ScopePermissions, type ScopePermissionsBulk, type UpdateBusinessUnitInput, type UpdateRoleInput };
|
package/dist/index.js
CHANGED
|
@@ -25,11 +25,25 @@ var ROAD_CORE_SUBJECTS = [
|
|
|
25
25
|
"Invitation"
|
|
26
26
|
];
|
|
27
27
|
var ROAD_WILDCARD_PERMISSION = "*";
|
|
28
|
+
|
|
29
|
+
// src/webhooks.ts
|
|
30
|
+
var ROAD_WEBHOOK_EVENT_TYPES = [
|
|
31
|
+
"organization.invitation.created",
|
|
32
|
+
"organization.invitation.accepted",
|
|
33
|
+
"organization.invitation.rejected",
|
|
34
|
+
"organization.invitation.cancelled",
|
|
35
|
+
"organization.member.joined",
|
|
36
|
+
"organization.member.suspended",
|
|
37
|
+
"organization.member.reinstated",
|
|
38
|
+
"organization.member.removed",
|
|
39
|
+
"organization.member.role-changed"
|
|
40
|
+
];
|
|
28
41
|
export {
|
|
29
42
|
ROAD_API_CONTRACT,
|
|
30
43
|
ROAD_API_URLS,
|
|
31
44
|
ROAD_CORE_ACTIONS,
|
|
32
45
|
ROAD_CORE_SUBJECTS,
|
|
46
|
+
ROAD_WEBHOOK_EVENT_TYPES,
|
|
33
47
|
ROAD_WILDCARD_PERMISSION
|
|
34
48
|
};
|
|
35
49
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api-contract.ts","../src/api-urls.ts","../src/permissions.ts"],"sourcesContent":["/**\n * The Road API **contract version** — the major boundary of the HTTP wire\n * surface. The Road API mounts every route under `/api/<contract>`, and every\n * SDK builds its base path as `${host}/api/${ROAD_API_CONTRACT}`.\n *\n * This is the single source of truth for that value. The Road API imports it\n * for its global prefix; the in-repo clients (admin, tester) and the published\n * SDKs read it from here. It is **not** environment configuration — it is\n * identical in every environment and changes only by a deliberate edit when the\n * wire contract makes a breaking change: `alpha` → `v1` → `v2`.\n *\n * Promoting this from `alpha` to `v1` is the trigger to take the SDKs to their\n * first stable `1.0.0`. See `docs/plans/14-sdk-publishing-and-versioning.md`.\n */\nexport const ROAD_API_CONTRACT = \"alpha\" as const;\n\nexport type RoadApiContract = typeof ROAD_API_CONTRACT;\n","/**\n * Road's hosted API base URLs. SDKs default to ROAD_API_URLS.production; the\n * sandbox URL is the deployed Road sandbox (override via the SDK's apiBaseUrl\n * config if you're running against a different environment, eg. local dev or\n * a private staging cluster).\n *\n * If the deployed sandbox hostname changes, update this constant — it's the\n * single source of truth every SDK reads from.\n */\nexport const ROAD_API_URLS = {\n production: \"https://api.road.app\",\n sandbox: \"https://api.road-sandbox.b1.app\",\n} as const;\n\nexport type RoadEnvironment = keyof typeof ROAD_API_URLS;\n","/**\n * Road IAM permission algebra. Permissions are `${action}:${subject}` strings;\n * the wildcard `\"*\"` short-circuits to true for every action in a scope.\n *\n * The widget catalog calls into actions and subjects Road ships by default\n * (the union types below). Platforms can declare their own actions and\n * subjects in their IAM catalog — those flow through useCan as plain strings,\n * still type-safe via `RoadPermission | (string & {})` in the React SDK.\n */\n\n/**\n * The CRUD verbs Road's IAM engine recognizes, plus `manage` which the\n * engine expands server-side into the full CRUD set for the same subject\n * (`manage:Member` ⇒ also `create|read|update|delete:Member` in the\n * effective-permissions response).\n *\n * Platforms can register their own actions (`approve`, `submit`, `list`, …)\n * — those flow through useCan as plain strings (the `(string & {})` part\n * of PermissionInput in the React SDK), still type-safe via that escape.\n */\nexport type RoadAction = \"create\" | \"read\" | \"update\" | \"delete\" | \"manage\";\n\n/**\n * Built-in subjects Road's own permissions cover. Mirrors the subjects\n * registered in the API's `Subjects` constant\n * (apps/api/src/modules/iam/authorization/constants/subjects.ts), limited\n * to the subjects user-facing widgets actually surface:\n *\n * - BusinessUnit: system-level — create new BUs\n * - BUDashboard: BU-level — read a BU's detail page\n * - BUSettings: BU-level — edit a BU's settings\n * - Member, Role, Permission, Invitation: BU-level CRUD\n *\n * Admin / platform-engineer subjects (System, Platform, AdminUser,\n * PlatformIdentity, …) are not exposed here — they belong to a future\n * developer-facing widget (and admin SDK), not the customer-facing toolkit.\n *\n * Platform-specific subjects (eg. A4L's `Agent`) are not enumerated —\n * platforms register them at runtime under their own scope, and useCan's\n * `(string & {})` accepts them without complaint.\n */\nexport type RoadCoreSubject =\n | \"BusinessUnit\"\n | \"BUDashboard\"\n | \"BUSettings\"\n | \"Member\"\n | \"Role\"\n | \"Permission\"\n | \"Invitation\";\n\n/** `${action}:${Subject}` for the core set, plus the wildcard. */\nexport type RoadPermission = `${RoadAction}:${RoadCoreSubject}` | \"*\";\n\n/** Runtime array of the core actions — handy for iteration or validation. */\nexport const ROAD_CORE_ACTIONS = [\n \"create\",\n \"read\",\n \"update\",\n \"delete\",\n \"manage\",\n] as const satisfies readonly RoadAction[];\n\n/** Runtime array of the core subjects — handy for iteration or validation. */\nexport const ROAD_CORE_SUBJECTS = [\n \"BusinessUnit\",\n \"BUDashboard\",\n \"BUSettings\",\n \"Member\",\n \"Role\",\n \"Permission\",\n \"Invitation\",\n] as const satisfies readonly RoadCoreSubject[];\n\n/** The wildcard permission string. Use this instead of literal \"*\" for grep-ability. */\nexport const ROAD_WILDCARD_PERMISSION = \"*\" as const;\n"],"mappings":";AAcO,IAAM,oBAAoB;;;ACL1B,IAAM,gBAAgB;AAAA,EAC3B,YAAY;AAAA,EACZ,SAAS;AACX;;;AC0CO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,2BAA2B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/api-contract.ts","../src/api-urls.ts","../src/permissions.ts","../src/webhooks.ts"],"sourcesContent":["/**\n * The Road API **contract version** — the major boundary of the HTTP wire\n * surface. The Road API mounts every route under `/api/<contract>`, and every\n * SDK builds its base path as `${host}/api/${ROAD_API_CONTRACT}`.\n *\n * This is the single source of truth for that value. The Road API imports it\n * for its global prefix; the in-repo clients (admin, tester) and the published\n * SDKs read it from here. It is **not** environment configuration — it is\n * identical in every environment and changes only by a deliberate edit when the\n * wire contract makes a breaking change: `alpha` → `v1` → `v2`.\n *\n * Promoting this from `alpha` to `v1` is the trigger to take the SDKs to their\n * first stable `1.0.0`. See `docs/plans/14-sdk-publishing-and-versioning.md`.\n */\nexport const ROAD_API_CONTRACT = \"alpha\" as const;\n\nexport type RoadApiContract = typeof ROAD_API_CONTRACT;\n","/**\n * Road's hosted API base URLs. SDKs default to ROAD_API_URLS.production; the\n * sandbox URL is the deployed Road sandbox (override via the SDK's apiBaseUrl\n * config if you're running against a different environment, eg. local dev or\n * a private staging cluster).\n *\n * If the deployed sandbox hostname changes, update this constant — it's the\n * single source of truth every SDK reads from.\n */\nexport const ROAD_API_URLS = {\n production: \"https://api.road.app\",\n sandbox: \"https://api.road-sandbox.b1.app\",\n} as const;\n\nexport type RoadEnvironment = keyof typeof ROAD_API_URLS;\n","/**\n * Road IAM permission algebra. Permissions are `${action}:${subject}` strings;\n * the wildcard `\"*\"` short-circuits to true for every action in a scope.\n *\n * The widget catalog calls into actions and subjects Road ships by default\n * (the union types below). Platforms can declare their own actions and\n * subjects in their IAM catalog — those flow through useCan as plain strings,\n * still type-safe via `RoadPermission | (string & {})` in the React SDK.\n */\n\n/**\n * The CRUD verbs Road's IAM engine recognizes, plus `manage` which the\n * engine expands server-side into the full CRUD set for the same subject\n * (`manage:Member` ⇒ also `create|read|update|delete:Member` in the\n * effective-permissions response).\n *\n * Platforms can register their own actions (`approve`, `submit`, `list`, …)\n * — those flow through useCan as plain strings (the `(string & {})` part\n * of PermissionInput in the React SDK), still type-safe via that escape.\n */\nexport type RoadAction = \"create\" | \"read\" | \"update\" | \"delete\" | \"manage\";\n\n/**\n * Built-in subjects Road's own permissions cover. Mirrors the subjects\n * registered in the API's `Subjects` constant\n * (apps/api/src/modules/iam/authorization/constants/subjects.ts), limited\n * to the subjects user-facing widgets actually surface:\n *\n * - BusinessUnit: system-level — create new BUs\n * - BUDashboard: BU-level — read a BU's detail page\n * - BUSettings: BU-level — edit a BU's settings\n * - Member, Role, Permission, Invitation: BU-level CRUD\n *\n * Admin / platform-engineer subjects (System, Platform, AdminUser,\n * PlatformIdentity, …) are not exposed here — they belong to a future\n * developer-facing widget (and admin SDK), not the customer-facing toolkit.\n *\n * Platform-specific subjects (eg. A4L's `Agent`) are not enumerated —\n * platforms register them at runtime under their own scope, and useCan's\n * `(string & {})` accepts them without complaint.\n */\nexport type RoadCoreSubject =\n | \"BusinessUnit\"\n | \"BUDashboard\"\n | \"BUSettings\"\n | \"Member\"\n | \"Role\"\n | \"Permission\"\n | \"Invitation\";\n\n/** `${action}:${Subject}` for the core set, plus the wildcard. */\nexport type RoadPermission = `${RoadAction}:${RoadCoreSubject}` | \"*\";\n\n/** Runtime array of the core actions — handy for iteration or validation. */\nexport const ROAD_CORE_ACTIONS = [\n \"create\",\n \"read\",\n \"update\",\n \"delete\",\n \"manage\",\n] as const satisfies readonly RoadAction[];\n\n/** Runtime array of the core subjects — handy for iteration or validation. */\nexport const ROAD_CORE_SUBJECTS = [\n \"BusinessUnit\",\n \"BUDashboard\",\n \"BUSettings\",\n \"Member\",\n \"Role\",\n \"Permission\",\n \"Invitation\",\n] as const satisfies readonly RoadCoreSubject[];\n\n/** The wildcard permission string. Use this instead of literal \"*\" for grep-ability. */\nexport const ROAD_WILDCARD_PERMISSION = \"*\" as const;\n","/**\n * Road webhook events — the canonical wire contract every SDK builds on.\n *\n * The event-type strings and `data` payloads mirror exactly what the Road API\n * delivers: the `event` and `data` fields of the webhook POST body, and the\n * `X-Road-Event` header. SDKs that receive webhooks import from here and never\n * redefine them (SDK DX Bar principle 11 — one source of truth).\n *\n * Only the public `organization.*` events are listed; internal/experimental\n * event namespaces are intentionally excluded from the SDK surface.\n */\n\n/** Payload for every `organization.invitation.*` event. */\nexport interface InvitationWebhookData {\n businessUnitId: string;\n invitationId: string;\n email: string;\n}\n\n/** Payload for `organization.member.{joined,suspended,reinstated,removed}`. */\nexport interface MemberWebhookData {\n businessUnitId: string;\n memberId: string;\n userId: string;\n}\n\n/** Payload for `organization.member.role-changed`. */\nexport interface MemberRoleChangedWebhookData extends MemberWebhookData {\n roleId: string;\n action: \"assigned\" | \"revoked\";\n}\n\n/** Maps each webhook event type to the shape of its `data` payload. */\nexport interface RoadWebhookPayloads {\n \"organization.invitation.created\": InvitationWebhookData;\n \"organization.invitation.accepted\": InvitationWebhookData;\n \"organization.invitation.rejected\": InvitationWebhookData;\n \"organization.invitation.cancelled\": InvitationWebhookData;\n \"organization.member.joined\": MemberWebhookData;\n \"organization.member.suspended\": MemberWebhookData;\n \"organization.member.reinstated\": MemberWebhookData;\n \"organization.member.removed\": MemberWebhookData;\n \"organization.member.role-changed\": MemberRoleChangedWebhookData;\n}\n\n/** Every webhook event type the Road API can deliver. */\nexport type RoadWebhookEventType = keyof RoadWebhookPayloads;\n\n/**\n * The exact envelope the Road API POSTs to a registered webhook URL —\n * mirrors the delivered body `{ id, event, timestamp, data }`.\n */\nexport interface RoadWebhookEvent<\n T extends RoadWebhookEventType = RoadWebhookEventType,\n> {\n /** Unique delivery id — also sent as the `X-Road-Delivery-Id` header. */\n id: string;\n /** The event type — also sent as the `X-Road-Event` header. */\n event: T;\n /** ISO-8601 timestamp of the delivery. */\n timestamp: string;\n /** Event-specific payload. */\n data: RoadWebhookPayloads[T];\n}\n\n/**\n * Runtime list of every webhook event type — handy for registering a\n * subscription to \"all events\". `satisfies` guarantees no typo'd or\n * stale entry slips in.\n */\nexport const ROAD_WEBHOOK_EVENT_TYPES = [\n \"organization.invitation.created\",\n \"organization.invitation.accepted\",\n \"organization.invitation.rejected\",\n \"organization.invitation.cancelled\",\n \"organization.member.joined\",\n \"organization.member.suspended\",\n \"organization.member.reinstated\",\n \"organization.member.removed\",\n \"organization.member.role-changed\",\n] as const satisfies readonly RoadWebhookEventType[];\n"],"mappings":";AAcO,IAAM,oBAAoB;;;ACL1B,IAAM,gBAAgB;AAAA,EAC3B,YAAY;AAAA,EACZ,SAAS;AACX;;;AC0CO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,2BAA2B;;;ACJjC,IAAM,2BAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b1-road/types",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared types and constants for every @b1-road SDK — entities, permission algebra, hosted API URLs.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,12 +27,24 @@
|
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
28
|
"exports": {
|
|
29
29
|
".": {
|
|
30
|
-
"import": {
|
|
31
|
-
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"require": {
|
|
35
|
+
"types": "./dist/index.d.cts",
|
|
36
|
+
"default": "./dist/index.cjs"
|
|
37
|
+
}
|
|
32
38
|
},
|
|
33
39
|
"./iam": {
|
|
34
|
-
"import": {
|
|
35
|
-
|
|
40
|
+
"import": {
|
|
41
|
+
"types": "./dist/iam.d.ts",
|
|
42
|
+
"default": "./dist/iam.js"
|
|
43
|
+
},
|
|
44
|
+
"require": {
|
|
45
|
+
"types": "./dist/iam.d.cts",
|
|
46
|
+
"default": "./dist/iam.cjs"
|
|
47
|
+
}
|
|
36
48
|
}
|
|
37
49
|
},
|
|
38
50
|
"files": [
|