@iveri/contracts 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -44,6 +44,17 @@ Anything needing a dependency belongs in `@iveri/nest-sdk` (backend) or `@iveri/
44
44
  `ErrorCode` — the stable, machine-readable error classification carried in every error
45
45
  response. Clients branch on `code`; `message` is for humans and may change at any time.
46
46
 
47
+ `UserPermission` + `ALL_USER_PERMISSIONS` — **one catalogue of permissions for the whole
48
+ platform**, not one per service. `iveri-identity-api` stores members on role rows, resolves
49
+ them into access tokens and validates custom-role input against `ALL_USER_PERMISSIONS`; every
50
+ other service reads them back out of the token to authorize a request; the frontend's
51
+ `<RequirePermission>` branches on the same values. A service defining its own enum locally
52
+ would find its permissions unassignable, because identity would reject them as unknown.
53
+
54
+ Values are `<resource>:<action>`, or `<service>:<resource>:<action>` where a resource name
55
+ would otherwise collide — identity's members are unprefixed because they predate the shared
56
+ catalogue and are already embedded in issued tokens and stored role rows.
57
+
47
58
  ## What is deliberately **not** here yet
48
59
 
49
60
  `event/` (domain event envelope, topics) and `api/` (per-service request/response shapes) are
@@ -52,8 +63,9 @@ needs them, per the second-consumer rule — not in anticipation.
52
63
 
53
64
  ## Adding to the contract
54
65
 
55
- - A new `ErrorCode` member is a **minor** version. Changing what an existing member means, or
56
- removing one, is **major** — clients branch on these.
66
+ - A new `ErrorCode` or `UserPermission` member is a **minor** version. Changing what an
67
+ existing member means, or removing one, is **major** — clients branch on these, and a
68
+ removed permission silently downgrades every live session whose token still carries it.
57
69
  - Widening a type is minor; narrowing it is major.
58
70
  - Breaking changes get a migration note in `CHANGELOG.md`. Services upgrade deliberately.
59
71
 
@@ -1,2 +1,3 @@
1
1
  export * from './error-code.enum.js';
2
+ export * from './user-permission.enum.js';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC"}
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./error-code.enum.js"), exports);
18
+ __exportStar(require("./user-permission.enum.js"), exports);
18
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,4DAA0C"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Every action a principal can be granted in an Iveri tenant, across every service.
3
+ *
4
+ * A permission is a **contract**, not an implementation detail: `iveri-identity-api` stores
5
+ * members on role rows and resolves them into access tokens, every other service reads them
6
+ * out of that token to authorize a request, and the frontend's `<RequirePermission>` branches
7
+ * on the same values. A member's wire value therefore never changes, and a member is never
8
+ * removed while issued tokens can still carry it — removing one silently downgrades every
9
+ * live session holding it. Adding one is a minor version.
10
+ *
11
+ * **One catalogue for the whole platform, deliberately.** Identity validates custom-role input
12
+ * against this list, so a permission it has never heard of cannot be granted. A service that
13
+ * defined its own enum locally would find its permissions unassignable.
14
+ *
15
+ * Values are `<resource>:<action>` — or `<service>:<resource>:<action>` where a resource name
16
+ * would otherwise collide across services — lowercase, so a token payload is readable in a
17
+ * log and a wildcard match (`role:*`) stays possible if we ever need one.
18
+ */
19
+ export declare enum UserPermission {
20
+ TENANT_READ = "tenant:read",
21
+ TENANT_UPDATE = "tenant:update",
22
+ /** Schedules the tenant for deletion. Owner-only; there is no undo path built yet. */
23
+ TENANT_DELETE = "tenant:delete",
24
+ USER_READ = "user:read",
25
+ USER_INVITE = "user:invite",
26
+ USER_UPDATE = "user:update",
27
+ USER_REMOVE = "user:remove",
28
+ MEMBERSHIP_READ = "membership:read",
29
+ /** Suspend or reactivate someone's access without deleting their account. */
30
+ MEMBERSHIP_UPDATE = "membership:update",
31
+ /**
32
+ * Change which roles a membership holds. Separate from `MEMBERSHIP_UPDATE` because
33
+ * granting roles is privilege escalation and deserves its own gate.
34
+ */
35
+ MEMBERSHIP_ASSIGN_ROLE = "membership:assign-role",
36
+ ROLE_READ = "role:read",
37
+ ROLE_CREATE = "role:create",
38
+ ROLE_UPDATE = "role:update",
39
+ ROLE_DELETE = "role:delete",
40
+ API_KEY_READ = "api-key:read",
41
+ API_KEY_ISSUE = "api-key:issue",
42
+ API_KEY_REVOKE = "api-key:revoke",
43
+ /** Read endpoint configuration. Never exposes the signing secret. */
44
+ CONDUIT_ENDPOINT_READ = "conduit:endpoint:read",
45
+ CONDUIT_ENDPOINT_CREATE = "conduit:endpoint:create",
46
+ CONDUIT_ENDPOINT_UPDATE = "conduit:endpoint:update",
47
+ CONDUIT_ENDPOINT_DELETE = "conduit:endpoint:delete",
48
+ /**
49
+ * List and read captured requests, **including their raw bodies and headers**. Captures
50
+ * hold whatever a provider sent — order details, message contents, personal data — so
51
+ * this is closer to a data-export permission than a config one.
52
+ */
53
+ CONDUIT_CAPTURE_READ = "conduit:capture:read",
54
+ CONDUIT_CAPTURE_DELETE = "conduit:capture:delete",
55
+ /**
56
+ * Resend a captured request to an arbitrary URL. Separate from `CONDUIT_CAPTURE_READ`
57
+ * because it makes an outbound request from our infrastructure with a body the caller
58
+ * controls, which is a materially different power from reading a row.
59
+ */
60
+ CONDUIT_REPLAY_EXECUTE = "conduit:replay:execute",
61
+ CONDUIT_PROVIDER_READ = "conduit:provider:read",
62
+ /** Define or amend a custom provider manifest — signature scheme, headers, handshake. */
63
+ CONDUIT_PROVIDER_MANAGE = "conduit:provider:manage"
64
+ }
65
+ /**
66
+ * Every member, for seeding the owner role and validating custom-role input.
67
+ *
68
+ * Frozen because it is shared mutable state in a browser bundle otherwise: one caller sorting
69
+ * it in place reorders it for everyone.
70
+ */
71
+ export declare const ALL_USER_PERMISSIONS: readonly UserPermission[];
72
+ //# sourceMappingURL=user-permission.enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-permission.enum.d.ts","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,oBAAY,cAAc;IAItB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,sFAAsF;IACtF,aAAa,kBAAkB;IAG/B,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAG3B,eAAe,oBAAoB;IACnC,6EAA6E;IAC7E,iBAAiB,sBAAsB;IACvC;;;OAGG;IACH,sBAAsB,2BAA2B;IAGjD,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAG3B,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IAKjC,qEAAqE;IACrE,qBAAqB,0BAA0B;IAC/C,uBAAuB,4BAA4B;IACnD,uBAAuB,4BAA4B;IACnD,uBAAuB,4BAA4B;IAGnD;;;;OAIG;IACH,oBAAoB,yBAAyB;IAC7C,sBAAsB,2BAA2B;IAGjD;;;;OAIG;IACH,sBAAsB,2BAA2B;IAGjD,qBAAqB,0BAA0B;IAC/C,yFAAyF;IACzF,uBAAuB,4BAA4B;CACtD;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,cAAc,EAAiD,CAAC"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALL_USER_PERMISSIONS = exports.UserPermission = void 0;
4
+ /**
5
+ * Every action a principal can be granted in an Iveri tenant, across every service.
6
+ *
7
+ * A permission is a **contract**, not an implementation detail: `iveri-identity-api` stores
8
+ * members on role rows and resolves them into access tokens, every other service reads them
9
+ * out of that token to authorize a request, and the frontend's `<RequirePermission>` branches
10
+ * on the same values. A member's wire value therefore never changes, and a member is never
11
+ * removed while issued tokens can still carry it — removing one silently downgrades every
12
+ * live session holding it. Adding one is a minor version.
13
+ *
14
+ * **One catalogue for the whole platform, deliberately.** Identity validates custom-role input
15
+ * against this list, so a permission it has never heard of cannot be granted. A service that
16
+ * defined its own enum locally would find its permissions unassignable.
17
+ *
18
+ * Values are `<resource>:<action>` — or `<service>:<resource>:<action>` where a resource name
19
+ * would otherwise collide across services — lowercase, so a token payload is readable in a
20
+ * log and a wildcard match (`role:*`) stays possible if we ever need one.
21
+ */
22
+ var UserPermission;
23
+ (function (UserPermission) {
24
+ // ══ iveri-identity-api ═══════════════════════════════════════════════════
25
+ // ── Tenant ──────────────────────────────────────────────────────────────
26
+ UserPermission["TENANT_READ"] = "tenant:read";
27
+ UserPermission["TENANT_UPDATE"] = "tenant:update";
28
+ /** Schedules the tenant for deletion. Owner-only; there is no undo path built yet. */
29
+ UserPermission["TENANT_DELETE"] = "tenant:delete";
30
+ // ── User ────────────────────────────────────────────────────────────────
31
+ UserPermission["USER_READ"] = "user:read";
32
+ UserPermission["USER_INVITE"] = "user:invite";
33
+ UserPermission["USER_UPDATE"] = "user:update";
34
+ UserPermission["USER_REMOVE"] = "user:remove";
35
+ // ── Membership ──────────────────────────────────────────────────────────
36
+ UserPermission["MEMBERSHIP_READ"] = "membership:read";
37
+ /** Suspend or reactivate someone's access without deleting their account. */
38
+ UserPermission["MEMBERSHIP_UPDATE"] = "membership:update";
39
+ /**
40
+ * Change which roles a membership holds. Separate from `MEMBERSHIP_UPDATE` because
41
+ * granting roles is privilege escalation and deserves its own gate.
42
+ */
43
+ UserPermission["MEMBERSHIP_ASSIGN_ROLE"] = "membership:assign-role";
44
+ // ── Role ────────────────────────────────────────────────────────────────
45
+ UserPermission["ROLE_READ"] = "role:read";
46
+ UserPermission["ROLE_CREATE"] = "role:create";
47
+ UserPermission["ROLE_UPDATE"] = "role:update";
48
+ UserPermission["ROLE_DELETE"] = "role:delete";
49
+ // ── API key ─────────────────────────────────────────────────────────────
50
+ UserPermission["API_KEY_READ"] = "api-key:read";
51
+ UserPermission["API_KEY_ISSUE"] = "api-key:issue";
52
+ UserPermission["API_KEY_REVOKE"] = "api-key:revoke";
53
+ // ══ conduit-api ══════════════════════════════════════════════════════════
54
+ // ── Endpoint ────────────────────────────────────────────────────────────
55
+ /** Read endpoint configuration. Never exposes the signing secret. */
56
+ UserPermission["CONDUIT_ENDPOINT_READ"] = "conduit:endpoint:read";
57
+ UserPermission["CONDUIT_ENDPOINT_CREATE"] = "conduit:endpoint:create";
58
+ UserPermission["CONDUIT_ENDPOINT_UPDATE"] = "conduit:endpoint:update";
59
+ UserPermission["CONDUIT_ENDPOINT_DELETE"] = "conduit:endpoint:delete";
60
+ // ── Capture ─────────────────────────────────────────────────────────────
61
+ /**
62
+ * List and read captured requests, **including their raw bodies and headers**. Captures
63
+ * hold whatever a provider sent — order details, message contents, personal data — so
64
+ * this is closer to a data-export permission than a config one.
65
+ */
66
+ UserPermission["CONDUIT_CAPTURE_READ"] = "conduit:capture:read";
67
+ UserPermission["CONDUIT_CAPTURE_DELETE"] = "conduit:capture:delete";
68
+ // ── Replay ──────────────────────────────────────────────────────────────
69
+ /**
70
+ * Resend a captured request to an arbitrary URL. Separate from `CONDUIT_CAPTURE_READ`
71
+ * because it makes an outbound request from our infrastructure with a body the caller
72
+ * controls, which is a materially different power from reading a row.
73
+ */
74
+ UserPermission["CONDUIT_REPLAY_EXECUTE"] = "conduit:replay:execute";
75
+ // ── Provider ────────────────────────────────────────────────────────────
76
+ UserPermission["CONDUIT_PROVIDER_READ"] = "conduit:provider:read";
77
+ /** Define or amend a custom provider manifest — signature scheme, headers, handshake. */
78
+ UserPermission["CONDUIT_PROVIDER_MANAGE"] = "conduit:provider:manage";
79
+ })(UserPermission || (exports.UserPermission = UserPermission = {}));
80
+ /**
81
+ * Every member, for seeding the owner role and validating custom-role input.
82
+ *
83
+ * Frozen because it is shared mutable state in a browser bundle otherwise: one caller sorting
84
+ * it in place reorders it for everyone.
85
+ */
86
+ exports.ALL_USER_PERMISSIONS = Object.freeze(Object.values(UserPermission));
87
+ //# sourceMappingURL=user-permission.enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-permission.enum.js","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,IAAY,cAkEX;AAlED,WAAY,cAAc;IACtB,4EAA4E;IAE5E,2EAA2E;IAC3E,6CAA2B,CAAA;IAC3B,iDAA+B,CAAA;IAC/B,sFAAsF;IACtF,iDAA+B,CAAA;IAE/B,2EAA2E;IAC3E,yCAAuB,CAAA;IACvB,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAE3B,2EAA2E;IAC3E,qDAAmC,CAAA;IACnC,6EAA6E;IAC7E,yDAAuC,CAAA;IACvC;;;OAGG;IACH,mEAAiD,CAAA;IAEjD,2EAA2E;IAC3E,yCAAuB,CAAA;IACvB,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAE3B,2EAA2E;IAC3E,+CAA6B,CAAA;IAC7B,iDAA+B,CAAA;IAC/B,mDAAiC,CAAA;IAEjC,4EAA4E;IAE5E,2EAA2E;IAC3E,qEAAqE;IACrE,iEAA+C,CAAA;IAC/C,qEAAmD,CAAA;IACnD,qEAAmD,CAAA;IACnD,qEAAmD,CAAA;IAEnD,2EAA2E;IAC3E;;;;OAIG;IACH,+DAA6C,CAAA;IAC7C,mEAAiD,CAAA;IAEjD,2EAA2E;IAC3E;;;;OAIG;IACH,mEAAiD,CAAA;IAEjD,2EAA2E;IAC3E,iEAA+C,CAAA;IAC/C,yFAAyF;IACzF,qEAAmD,CAAA;AACvD,CAAC,EAlEW,cAAc,8BAAd,cAAc,QAkEzB;AAED;;;;;GAKG;AACU,QAAA,oBAAoB,GAA8B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export * from './error-code.enum.js';
2
+ export * from './user-permission.enum.js';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export * from './error-code.enum.js';
2
+ export * from './user-permission.enum.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/enum/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Every action a principal can be granted in an Iveri tenant, across every service.
3
+ *
4
+ * A permission is a **contract**, not an implementation detail: `iveri-identity-api` stores
5
+ * members on role rows and resolves them into access tokens, every other service reads them
6
+ * out of that token to authorize a request, and the frontend's `<RequirePermission>` branches
7
+ * on the same values. A member's wire value therefore never changes, and a member is never
8
+ * removed while issued tokens can still carry it — removing one silently downgrades every
9
+ * live session holding it. Adding one is a minor version.
10
+ *
11
+ * **One catalogue for the whole platform, deliberately.** Identity validates custom-role input
12
+ * against this list, so a permission it has never heard of cannot be granted. A service that
13
+ * defined its own enum locally would find its permissions unassignable.
14
+ *
15
+ * Values are `<resource>:<action>` — or `<service>:<resource>:<action>` where a resource name
16
+ * would otherwise collide across services — lowercase, so a token payload is readable in a
17
+ * log and a wildcard match (`role:*`) stays possible if we ever need one.
18
+ */
19
+ export declare enum UserPermission {
20
+ TENANT_READ = "tenant:read",
21
+ TENANT_UPDATE = "tenant:update",
22
+ /** Schedules the tenant for deletion. Owner-only; there is no undo path built yet. */
23
+ TENANT_DELETE = "tenant:delete",
24
+ USER_READ = "user:read",
25
+ USER_INVITE = "user:invite",
26
+ USER_UPDATE = "user:update",
27
+ USER_REMOVE = "user:remove",
28
+ MEMBERSHIP_READ = "membership:read",
29
+ /** Suspend or reactivate someone's access without deleting their account. */
30
+ MEMBERSHIP_UPDATE = "membership:update",
31
+ /**
32
+ * Change which roles a membership holds. Separate from `MEMBERSHIP_UPDATE` because
33
+ * granting roles is privilege escalation and deserves its own gate.
34
+ */
35
+ MEMBERSHIP_ASSIGN_ROLE = "membership:assign-role",
36
+ ROLE_READ = "role:read",
37
+ ROLE_CREATE = "role:create",
38
+ ROLE_UPDATE = "role:update",
39
+ ROLE_DELETE = "role:delete",
40
+ API_KEY_READ = "api-key:read",
41
+ API_KEY_ISSUE = "api-key:issue",
42
+ API_KEY_REVOKE = "api-key:revoke",
43
+ /** Read endpoint configuration. Never exposes the signing secret. */
44
+ CONDUIT_ENDPOINT_READ = "conduit:endpoint:read",
45
+ CONDUIT_ENDPOINT_CREATE = "conduit:endpoint:create",
46
+ CONDUIT_ENDPOINT_UPDATE = "conduit:endpoint:update",
47
+ CONDUIT_ENDPOINT_DELETE = "conduit:endpoint:delete",
48
+ /**
49
+ * List and read captured requests, **including their raw bodies and headers**. Captures
50
+ * hold whatever a provider sent — order details, message contents, personal data — so
51
+ * this is closer to a data-export permission than a config one.
52
+ */
53
+ CONDUIT_CAPTURE_READ = "conduit:capture:read",
54
+ CONDUIT_CAPTURE_DELETE = "conduit:capture:delete",
55
+ /**
56
+ * Resend a captured request to an arbitrary URL. Separate from `CONDUIT_CAPTURE_READ`
57
+ * because it makes an outbound request from our infrastructure with a body the caller
58
+ * controls, which is a materially different power from reading a row.
59
+ */
60
+ CONDUIT_REPLAY_EXECUTE = "conduit:replay:execute",
61
+ CONDUIT_PROVIDER_READ = "conduit:provider:read",
62
+ /** Define or amend a custom provider manifest — signature scheme, headers, handshake. */
63
+ CONDUIT_PROVIDER_MANAGE = "conduit:provider:manage"
64
+ }
65
+ /**
66
+ * Every member, for seeding the owner role and validating custom-role input.
67
+ *
68
+ * Frozen because it is shared mutable state in a browser bundle otherwise: one caller sorting
69
+ * it in place reorders it for everyone.
70
+ */
71
+ export declare const ALL_USER_PERMISSIONS: readonly UserPermission[];
72
+ //# sourceMappingURL=user-permission.enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-permission.enum.d.ts","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,oBAAY,cAAc;IAItB,WAAW,gBAAgB;IAC3B,aAAa,kBAAkB;IAC/B,sFAAsF;IACtF,aAAa,kBAAkB;IAG/B,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAG3B,eAAe,oBAAoB;IACnC,6EAA6E;IAC7E,iBAAiB,sBAAsB;IACvC;;;OAGG;IACH,sBAAsB,2BAA2B;IAGjD,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAG3B,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IAKjC,qEAAqE;IACrE,qBAAqB,0BAA0B;IAC/C,uBAAuB,4BAA4B;IACnD,uBAAuB,4BAA4B;IACnD,uBAAuB,4BAA4B;IAGnD;;;;OAIG;IACH,oBAAoB,yBAAyB;IAC7C,sBAAsB,2BAA2B;IAGjD;;;;OAIG;IACH,sBAAsB,2BAA2B;IAGjD,qBAAqB,0BAA0B;IAC/C,yFAAyF;IACzF,uBAAuB,4BAA4B;CACtD;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,cAAc,EAAiD,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Every action a principal can be granted in an Iveri tenant, across every service.
3
+ *
4
+ * A permission is a **contract**, not an implementation detail: `iveri-identity-api` stores
5
+ * members on role rows and resolves them into access tokens, every other service reads them
6
+ * out of that token to authorize a request, and the frontend's `<RequirePermission>` branches
7
+ * on the same values. A member's wire value therefore never changes, and a member is never
8
+ * removed while issued tokens can still carry it — removing one silently downgrades every
9
+ * live session holding it. Adding one is a minor version.
10
+ *
11
+ * **One catalogue for the whole platform, deliberately.** Identity validates custom-role input
12
+ * against this list, so a permission it has never heard of cannot be granted. A service that
13
+ * defined its own enum locally would find its permissions unassignable.
14
+ *
15
+ * Values are `<resource>:<action>` — or `<service>:<resource>:<action>` where a resource name
16
+ * would otherwise collide across services — lowercase, so a token payload is readable in a
17
+ * log and a wildcard match (`role:*`) stays possible if we ever need one.
18
+ */
19
+ export var UserPermission;
20
+ (function (UserPermission) {
21
+ // ══ iveri-identity-api ═══════════════════════════════════════════════════
22
+ // ── Tenant ──────────────────────────────────────────────────────────────
23
+ UserPermission["TENANT_READ"] = "tenant:read";
24
+ UserPermission["TENANT_UPDATE"] = "tenant:update";
25
+ /** Schedules the tenant for deletion. Owner-only; there is no undo path built yet. */
26
+ UserPermission["TENANT_DELETE"] = "tenant:delete";
27
+ // ── User ────────────────────────────────────────────────────────────────
28
+ UserPermission["USER_READ"] = "user:read";
29
+ UserPermission["USER_INVITE"] = "user:invite";
30
+ UserPermission["USER_UPDATE"] = "user:update";
31
+ UserPermission["USER_REMOVE"] = "user:remove";
32
+ // ── Membership ──────────────────────────────────────────────────────────
33
+ UserPermission["MEMBERSHIP_READ"] = "membership:read";
34
+ /** Suspend or reactivate someone's access without deleting their account. */
35
+ UserPermission["MEMBERSHIP_UPDATE"] = "membership:update";
36
+ /**
37
+ * Change which roles a membership holds. Separate from `MEMBERSHIP_UPDATE` because
38
+ * granting roles is privilege escalation and deserves its own gate.
39
+ */
40
+ UserPermission["MEMBERSHIP_ASSIGN_ROLE"] = "membership:assign-role";
41
+ // ── Role ────────────────────────────────────────────────────────────────
42
+ UserPermission["ROLE_READ"] = "role:read";
43
+ UserPermission["ROLE_CREATE"] = "role:create";
44
+ UserPermission["ROLE_UPDATE"] = "role:update";
45
+ UserPermission["ROLE_DELETE"] = "role:delete";
46
+ // ── API key ─────────────────────────────────────────────────────────────
47
+ UserPermission["API_KEY_READ"] = "api-key:read";
48
+ UserPermission["API_KEY_ISSUE"] = "api-key:issue";
49
+ UserPermission["API_KEY_REVOKE"] = "api-key:revoke";
50
+ // ══ conduit-api ══════════════════════════════════════════════════════════
51
+ // ── Endpoint ────────────────────────────────────────────────────────────
52
+ /** Read endpoint configuration. Never exposes the signing secret. */
53
+ UserPermission["CONDUIT_ENDPOINT_READ"] = "conduit:endpoint:read";
54
+ UserPermission["CONDUIT_ENDPOINT_CREATE"] = "conduit:endpoint:create";
55
+ UserPermission["CONDUIT_ENDPOINT_UPDATE"] = "conduit:endpoint:update";
56
+ UserPermission["CONDUIT_ENDPOINT_DELETE"] = "conduit:endpoint:delete";
57
+ // ── Capture ─────────────────────────────────────────────────────────────
58
+ /**
59
+ * List and read captured requests, **including their raw bodies and headers**. Captures
60
+ * hold whatever a provider sent — order details, message contents, personal data — so
61
+ * this is closer to a data-export permission than a config one.
62
+ */
63
+ UserPermission["CONDUIT_CAPTURE_READ"] = "conduit:capture:read";
64
+ UserPermission["CONDUIT_CAPTURE_DELETE"] = "conduit:capture:delete";
65
+ // ── Replay ──────────────────────────────────────────────────────────────
66
+ /**
67
+ * Resend a captured request to an arbitrary URL. Separate from `CONDUIT_CAPTURE_READ`
68
+ * because it makes an outbound request from our infrastructure with a body the caller
69
+ * controls, which is a materially different power from reading a row.
70
+ */
71
+ UserPermission["CONDUIT_REPLAY_EXECUTE"] = "conduit:replay:execute";
72
+ // ── Provider ────────────────────────────────────────────────────────────
73
+ UserPermission["CONDUIT_PROVIDER_READ"] = "conduit:provider:read";
74
+ /** Define or amend a custom provider manifest — signature scheme, headers, handshake. */
75
+ UserPermission["CONDUIT_PROVIDER_MANAGE"] = "conduit:provider:manage";
76
+ })(UserPermission || (UserPermission = {}));
77
+ /**
78
+ * Every member, for seeding the owner role and validating custom-role input.
79
+ *
80
+ * Frozen because it is shared mutable state in a browser bundle otherwise: one caller sorting
81
+ * it in place reorders it for everyone.
82
+ */
83
+ export const ALL_USER_PERMISSIONS = Object.freeze(Object.values(UserPermission));
84
+ //# sourceMappingURL=user-permission.enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-permission.enum.js","sourceRoot":"","sources":["../../../src/enum/user-permission.enum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAN,IAAY,cAkEX;AAlED,WAAY,cAAc;IACtB,4EAA4E;IAE5E,2EAA2E;IAC3E,6CAA2B,CAAA;IAC3B,iDAA+B,CAAA;IAC/B,sFAAsF;IACtF,iDAA+B,CAAA;IAE/B,2EAA2E;IAC3E,yCAAuB,CAAA;IACvB,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAE3B,2EAA2E;IAC3E,qDAAmC,CAAA;IACnC,6EAA6E;IAC7E,yDAAuC,CAAA;IACvC;;;OAGG;IACH,mEAAiD,CAAA;IAEjD,2EAA2E;IAC3E,yCAAuB,CAAA;IACvB,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAC3B,6CAA2B,CAAA;IAE3B,2EAA2E;IAC3E,+CAA6B,CAAA;IAC7B,iDAA+B,CAAA;IAC/B,mDAAiC,CAAA;IAEjC,4EAA4E;IAE5E,2EAA2E;IAC3E,qEAAqE;IACrE,iEAA+C,CAAA;IAC/C,qEAAmD,CAAA;IACnD,qEAAmD,CAAA;IACnD,qEAAmD,CAAA;IAEnD,2EAA2E;IAC3E;;;;OAIG;IACH,+DAA6C,CAAA;IAC7C,mEAAiD,CAAA;IAEjD,2EAA2E;IAC3E;;;;OAIG;IACH,mEAAiD,CAAA;IAEjD,2EAA2E;IAC3E,iEAA+C,CAAA;IAC/C,yFAAyF;IACzF,qEAAmD,CAAA;AACvD,CAAC,EAlEW,cAAc,KAAd,cAAc,QAkEzB;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAA8B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iveri/contracts",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Wire contracts shared by every Iveri backend and frontend. Zero runtime dependencies.",
5
5
  "license": "MIT",
6
6
  "repository": {