@noodleseed/one 0.99.0 → 0.100.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 (178) hide show
  1. package/dist/commands/auth-ops.d.ts.map +1 -1
  2. package/dist/commands/auth-ops.js +6 -1
  3. package/dist/commands/auth-ops.js.map +1 -1
  4. package/dist/commands/auth-service-principals.d.ts +3 -0
  5. package/dist/commands/auth-service-principals.d.ts.map +1 -0
  6. package/dist/commands/auth-service-principals.js +380 -0
  7. package/dist/commands/auth-service-principals.js.map +1 -0
  8. package/dist/commands/catalog-data-auth-discovery.d.ts.map +1 -1
  9. package/dist/commands/catalog-data-auth-discovery.js +187 -2
  10. package/dist/commands/catalog-data-auth-discovery.js.map +1 -1
  11. package/dist/commands/catalog.d.ts.map +1 -1
  12. package/dist/commands/catalog.js +1 -0
  13. package/dist/commands/catalog.js.map +1 -1
  14. package/node_modules/@noodle-borg/auth/dist/index.d.ts +1 -1
  15. package/node_modules/@noodle-borg/auth/dist/index.d.ts.map +1 -1
  16. package/node_modules/@noodle-borg/auth/dist/index.js.map +1 -1
  17. package/node_modules/@noodle-borg/auth/dist/jwt-issuer.d.ts +5 -1
  18. package/node_modules/@noodle-borg/auth/dist/jwt-issuer.d.ts.map +1 -1
  19. package/node_modules/@noodle-borg/auth/dist/jwt-issuer.js +6 -0
  20. package/node_modules/@noodle-borg/auth/dist/jwt-issuer.js.map +1 -1
  21. package/node_modules/@noodle-borg/auth/dist/verify.d.ts +9 -2
  22. package/node_modules/@noodle-borg/auth/dist/verify.d.ts.map +1 -1
  23. package/node_modules/@noodle-borg/auth/dist/verify.js +25 -1
  24. package/node_modules/@noodle-borg/auth/dist/verify.js.map +1 -1
  25. package/node_modules/@noodle-borg/capabilities/dist/index.d.ts.map +1 -1
  26. package/node_modules/@noodle-borg/capabilities/dist/index.js +7 -0
  27. package/node_modules/@noodle-borg/capabilities/dist/index.js.map +1 -1
  28. package/node_modules/@noodle-borg/module/dist/contract.d.ts +1 -1
  29. package/node_modules/@noodle-borg/module/dist/contract.d.ts.map +1 -1
  30. package/node_modules/@noodle-borg/protocol/dist/index.d.ts +1 -0
  31. package/node_modules/@noodle-borg/protocol/dist/index.d.ts.map +1 -1
  32. package/node_modules/@noodle-borg/protocol/dist/index.js +1 -0
  33. package/node_modules/@noodle-borg/protocol/dist/index.js.map +1 -1
  34. package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +2 -0
  35. package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts.map +1 -1
  36. package/node_modules/@noodle-borg/protocol/dist/sdk-server.js.map +1 -1
  37. package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.d.ts +6 -0
  38. package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.d.ts.map +1 -0
  39. package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.js +6 -0
  40. package/node_modules/@noodle-borg/protocol/dist/tool-confirmation.js.map +1 -0
  41. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.d.ts +1 -1
  42. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.d.ts.map +1 -1
  43. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.js +2 -2
  44. package/node_modules/@noodle-borg/protocol/dist/tool-interaction.js.map +1 -1
  45. package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.d.ts +1 -1
  46. package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.d.ts.map +1 -1
  47. package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.js +2 -2
  48. package/node_modules/@noodle-borg/protocol/dist/v2/confirmation.js.map +1 -1
  49. package/node_modules/@noodle-borg/protocol/dist/v2/input-required.d.ts.map +1 -1
  50. package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js +5 -0
  51. package/node_modules/@noodle-borg/protocol/dist/v2/input-required.js.map +1 -1
  52. package/node_modules/@noodle-borg/protocol/dist/v2/server.d.ts.map +1 -1
  53. package/node_modules/@noodle-borg/protocol/dist/v2/server.js +13 -9
  54. package/node_modules/@noodle-borg/protocol/dist/v2/server.js.map +1 -1
  55. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +1 -1
  56. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts.map +1 -1
  57. package/node_modules/@noodle-borg/service/dist/index.d.ts +4 -0
  58. package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
  59. package/node_modules/@noodle-borg/service/dist/index.js +4 -0
  60. package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
  61. package/node_modules/@noodle-borg/service/dist/oauth/app.d.ts +2 -0
  62. package/node_modules/@noodle-borg/service/dist/oauth/app.d.ts.map +1 -1
  63. package/node_modules/@noodle-borg/service/dist/oauth/app.js +29 -0
  64. package/node_modules/@noodle-borg/service/dist/oauth/app.js.map +1 -1
  65. package/node_modules/@noodle-borg/service/dist/oauth/metadata.d.ts +1 -1
  66. package/node_modules/@noodle-borg/service/dist/oauth/metadata.d.ts.map +1 -1
  67. package/node_modules/@noodle-borg/service/dist/oauth/metadata.js +19 -2
  68. package/node_modules/@noodle-borg/service/dist/oauth/metadata.js.map +1 -1
  69. package/node_modules/@noodle-borg/service/dist/oauth/platform-principal-guard.d.ts.map +1 -1
  70. package/node_modules/@noodle-borg/service/dist/oauth/platform-principal-guard.js +3 -1
  71. package/node_modules/@noodle-borg/service/dist/oauth/platform-principal-guard.js.map +1 -1
  72. package/node_modules/@noodle-borg/service/dist/oauth/provider.d.ts +5 -0
  73. package/node_modules/@noodle-borg/service/dist/oauth/provider.d.ts.map +1 -1
  74. package/node_modules/@noodle-borg/service/dist/oauth/provider.js +11 -1
  75. package/node_modules/@noodle-borg/service/dist/oauth/provider.js.map +1 -1
  76. package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.d.ts +8 -1
  77. package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.d.ts.map +1 -1
  78. package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.js +60 -0
  79. package/node_modules/@noodle-borg/service/dist/oauth/service-bootstrap.js.map +1 -1
  80. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.d.ts +22 -0
  81. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.d.ts.map +1 -0
  82. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.js +199 -0
  83. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-client-auth.js.map +1 -0
  84. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.d.ts +14 -0
  85. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.d.ts.map +1 -0
  86. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.js +119 -0
  87. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-credentials.js.map +1 -0
  88. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.d.ts +16 -0
  89. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.d.ts.map +1 -0
  90. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.js +34 -0
  91. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-guard.js.map +1 -0
  92. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.d.ts +14 -0
  93. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.d.ts.map +1 -0
  94. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.js +53 -0
  95. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-resource.js.map +1 -0
  96. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.d.ts +4 -0
  97. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.d.ts.map +1 -0
  98. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.js +98 -0
  99. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres-schema.js.map +1 -0
  100. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.d.ts +22 -0
  101. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.d.ts.map +1 -0
  102. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.js +359 -0
  103. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store-postgres.js.map +1 -0
  104. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.d.ts +165 -0
  105. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.d.ts.map +1 -0
  106. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.js +349 -0
  107. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-store.js.map +1 -0
  108. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.d.ts +20 -0
  109. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.d.ts.map +1 -0
  110. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.js +175 -0
  111. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-handler.js.map +1 -0
  112. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.d.ts +12 -0
  113. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.d.ts.map +1 -0
  114. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.js +20 -0
  115. package/node_modules/@noodle-borg/service/dist/oauth/service-principal-token-issuer.js.map +1 -0
  116. package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.d.ts +9 -3
  117. package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.d.ts.map +1 -1
  118. package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.js +6 -0
  119. package/node_modules/@noodle-borg/service/dist/oauth/token-issuer.js.map +1 -1
  120. package/node_modules/@noodle-borg/service/dist/options.d.ts +5 -0
  121. package/node_modules/@noodle-borg/service/dist/options.d.ts.map +1 -1
  122. package/node_modules/@noodle-borg/service/dist/routes/feedback-operations-dispatch.d.ts +2 -1
  123. package/node_modules/@noodle-borg/service/dist/routes/feedback-operations-dispatch.d.ts.map +1 -1
  124. package/node_modules/@noodle-borg/service/dist/routes/feedback-operations-dispatch.js +2 -1
  125. package/node_modules/@noodle-borg/service/dist/routes/feedback-operations-dispatch.js.map +1 -1
  126. package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.d.ts +24 -0
  127. package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.d.ts.map +1 -0
  128. package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.js +55 -0
  129. package/node_modules/@noodle-borg/service/dist/routes/service-principal-contracts.js.map +1 -0
  130. package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.d.ts +29 -0
  131. package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.d.ts.map +1 -0
  132. package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.js +63 -0
  133. package/node_modules/@noodle-borg/service/dist/routes/service-principal-paths.js.map +1 -0
  134. package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.d.ts +27 -0
  135. package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.d.ts.map +1 -0
  136. package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.js +33 -0
  137. package/node_modules/@noodle-borg/service/dist/routes/service-principals-dispatch.js.map +1 -0
  138. package/node_modules/@noodle-borg/service/dist/routes/service-principals.d.ts +17 -0
  139. package/node_modules/@noodle-borg/service/dist/routes/service-principals.d.ts.map +1 -0
  140. package/node_modules/@noodle-borg/service/dist/routes/service-principals.js +203 -0
  141. package/node_modules/@noodle-borg/service/dist/routes/service-principals.js.map +1 -0
  142. package/node_modules/@noodle-borg/service/dist/routes/slack-feedback-actions.d.ts +2 -0
  143. package/node_modules/@noodle-borg/service/dist/routes/slack-feedback-actions.d.ts.map +1 -1
  144. package/node_modules/@noodle-borg/service/dist/routes/slack-feedback-actions.js +44 -14
  145. package/node_modules/@noodle-borg/service/dist/routes/slack-feedback-actions.js.map +1 -1
  146. package/node_modules/@noodle-borg/service/dist/serve.d.ts.map +1 -1
  147. package/node_modules/@noodle-borg/service/dist/serve.js +4 -1
  148. package/node_modules/@noodle-borg/service/dist/serve.js.map +1 -1
  149. package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.d.ts +12 -0
  150. package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.d.ts.map +1 -0
  151. package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.js +71 -0
  152. package/node_modules/@noodle-borg/service/dist/service-principal-data-plane.js.map +1 -0
  153. package/node_modules/@noodle-borg/service/dist/service.d.ts +1 -3
  154. package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
  155. package/node_modules/@noodle-borg/service/dist/service.js +9 -5
  156. package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
  157. package/node_modules/@noodle-borg/service/package.json +1 -0
  158. package/node_modules/@noodle-borg/transport-http/dist/handler.d.ts +5 -0
  159. package/node_modules/@noodle-borg/transport-http/dist/handler.d.ts.map +1 -1
  160. package/node_modules/@noodle-borg/transport-http/dist/handler.js +4 -0
  161. package/node_modules/@noodle-borg/transport-http/dist/handler.js.map +1 -1
  162. package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.d.ts +5 -0
  163. package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.d.ts.map +1 -1
  164. package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.js +16 -0
  165. package/node_modules/@noodle-borg/transport-http/dist/identity-authorization.js.map +1 -1
  166. package/node_modules/@noodle-borg/transport-http/dist/index.d.ts +2 -0
  167. package/node_modules/@noodle-borg/transport-http/dist/index.d.ts.map +1 -1
  168. package/node_modules/@noodle-borg/transport-http/dist/index.js +1 -0
  169. package/node_modules/@noodle-borg/transport-http/dist/index.js.map +1 -1
  170. package/node_modules/@noodle-borg/transport-http/dist/serve-request.d.ts +3 -0
  171. package/node_modules/@noodle-borg/transport-http/dist/serve-request.d.ts.map +1 -1
  172. package/node_modules/@noodle-borg/transport-http/dist/serve-request.js +56 -2
  173. package/node_modules/@noodle-borg/transport-http/dist/serve-request.js.map +1 -1
  174. package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.d.ts +31 -0
  175. package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.d.ts.map +1 -0
  176. package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.js +51 -0
  177. package/node_modules/@noodle-borg/transport-http/dist/service-principal-authorization.js.map +1 -0
  178. package/package.json +1 -1
@@ -0,0 +1,349 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { validateSlug } from '../store/validate.js';
3
+ import { validatePublicJwk, } from './service-principal-credentials.js';
4
+ export class InMemoryServicePrincipalStore {
5
+ #principals = new Map();
6
+ #grants = new Map();
7
+ #credentials = new Map();
8
+ #assertionJtis = new Map();
9
+ #now;
10
+ constructor(options = {}) {
11
+ this.#now = options.now ?? (() => new Date());
12
+ }
13
+ async createPrincipal(input) {
14
+ const now = currentServicePrincipalTimestamp(this.#now);
15
+ const record = {
16
+ principalId: `spn_${randomUUID()}`,
17
+ org: validateSlug('org', input.org),
18
+ name: validateServicePrincipalDisplayName('service-principal name', input.name),
19
+ status: 'active',
20
+ createdBySubject: validateServicePrincipalActor(input.actorSubject),
21
+ createdAt: now,
22
+ updatedAt: now,
23
+ };
24
+ this.#principals.set(record.principalId, record);
25
+ return clone(record);
26
+ }
27
+ async listPrincipals(org) {
28
+ const normalizedOrg = validateSlug('org', org);
29
+ return [...this.#principals.values()]
30
+ .filter((record) => record.org === normalizedOrg)
31
+ .sort((left, right) => left.principalId.localeCompare(right.principalId))
32
+ .map(clone);
33
+ }
34
+ async getPrincipal(input) {
35
+ const principal = this.#ownedPrincipal(input, false);
36
+ if (principal === undefined)
37
+ return undefined;
38
+ return {
39
+ principal: clone(principal),
40
+ grants: [...this.#grants.values()]
41
+ .filter((grant) => grant.principalId === principal.principalId)
42
+ .sort((left, right) => left.grantId.localeCompare(right.grantId))
43
+ .map(clone),
44
+ credentials: [...this.#credentials.values()]
45
+ .filter((credential) => credential.principalId === principal.principalId)
46
+ .sort((left, right) => left.credentialId.localeCompare(right.credentialId))
47
+ .map(publicServicePrincipalCredential),
48
+ };
49
+ }
50
+ async revokePrincipal(input) {
51
+ validateServicePrincipalActor(input.actorSubject);
52
+ const principal = this.#ownedPrincipal(input, false);
53
+ if (principal === undefined)
54
+ return false;
55
+ if (principal.status === 'revoked')
56
+ return true;
57
+ const now = currentServicePrincipalTimestamp(this.#now);
58
+ this.#principals.set(principal.principalId, {
59
+ ...principal,
60
+ status: 'revoked',
61
+ updatedAt: now,
62
+ revokedAt: now,
63
+ revokedBySubject: input.actorSubject,
64
+ });
65
+ return true;
66
+ }
67
+ async createGrant(input) {
68
+ const principal = this.#requireActivePrincipal(input);
69
+ const app = validateSlug('app', input.app);
70
+ const environment = validateSlug('env', input.environment);
71
+ if ([...this.#grants.values()].some((grant) => grant.principalId === principal.principalId &&
72
+ grant.app === app &&
73
+ grant.environment === environment &&
74
+ grant.status === 'active')) {
75
+ throw new Error('service principal already has an active grant for this app and environment');
76
+ }
77
+ const now = currentServicePrincipalTimestamp(this.#now);
78
+ const record = {
79
+ grantId: `spg_${randomUUID()}`,
80
+ principalId: principal.principalId,
81
+ org: principal.org,
82
+ app,
83
+ environment,
84
+ scopes: normalizeServicePrincipalScopes(input.scopes),
85
+ status: 'active',
86
+ createdBySubject: validateServicePrincipalActor(input.actorSubject),
87
+ createdAt: now,
88
+ updatedAt: now,
89
+ };
90
+ this.#grants.set(record.grantId, record);
91
+ return clone(record);
92
+ }
93
+ async revokeGrant(input) {
94
+ validateServicePrincipalActor(input.actorSubject);
95
+ const principal = this.#ownedPrincipal(input, true);
96
+ const grant = this.#grants.get(input.grantId);
97
+ if (principal === undefined ||
98
+ grant === undefined ||
99
+ grant.principalId !== principal.principalId) {
100
+ return false;
101
+ }
102
+ if (grant.status === 'revoked')
103
+ return true;
104
+ const now = currentServicePrincipalTimestamp(this.#now);
105
+ this.#grants.set(grant.grantId, {
106
+ ...grant,
107
+ status: 'revoked',
108
+ updatedAt: now,
109
+ revokedAt: now,
110
+ revokedBySubject: input.actorSubject,
111
+ });
112
+ return true;
113
+ }
114
+ async createCredential(input) {
115
+ const principal = this.#requireActivePrincipal(input);
116
+ const nowDate = currentServicePrincipalDate(this.#now);
117
+ const activeOfKind = [...this.#credentials.values()].filter((credential) => credential.principalId === principal.principalId &&
118
+ credential.kind === input.kind &&
119
+ servicePrincipalCredentialIsActive(credential, nowDate.getTime()));
120
+ if (activeOfKind.length >= 5) {
121
+ throw new Error(`service principal may have at most five active ${input.kind} credentials`);
122
+ }
123
+ const createdAt = nowDate.toISOString();
124
+ const expiresAt = normalizeServicePrincipalExpiry(input.expiresAt, nowDate);
125
+ const base = {
126
+ credentialId: `spc_${randomUUID()}`,
127
+ principalId: principal.principalId,
128
+ label: validateServicePrincipalDisplayName('credential label', input.label),
129
+ status: 'active',
130
+ createdBySubject: validateServicePrincipalActor(input.actorSubject),
131
+ createdAt,
132
+ updatedAt: createdAt,
133
+ ...(expiresAt === undefined ? {} : { expiresAt }),
134
+ };
135
+ let stored;
136
+ if (input.kind === 'client_secret') {
137
+ stored = {
138
+ ...base,
139
+ kind: 'client_secret',
140
+ secretDigest: validateServicePrincipalSecretDigest(input.secretDigest),
141
+ };
142
+ }
143
+ else {
144
+ const validated = await validatePublicJwk(input.publicJwk, input.algorithm);
145
+ const kid = validated.publicJwk.kid;
146
+ stored = {
147
+ ...base,
148
+ kind: 'public_jwk',
149
+ algorithm: validated.algorithm,
150
+ publicJwk: validated.publicJwk,
151
+ ...(typeof kid === 'string' ? { kid } : {}),
152
+ };
153
+ }
154
+ this.#credentials.set(stored.credentialId, stored);
155
+ return publicServicePrincipalCredential(stored);
156
+ }
157
+ async revokeCredential(input) {
158
+ validateServicePrincipalActor(input.actorSubject);
159
+ const principal = this.#ownedPrincipal(input, true);
160
+ const credential = this.#credentials.get(input.credentialId);
161
+ if (principal === undefined ||
162
+ credential === undefined ||
163
+ credential.principalId !== principal.principalId) {
164
+ return false;
165
+ }
166
+ if (credential.status === 'revoked')
167
+ return true;
168
+ const now = currentServicePrincipalTimestamp(this.#now);
169
+ this.#credentials.set(credential.credentialId, {
170
+ ...credential,
171
+ status: 'revoked',
172
+ updatedAt: now,
173
+ revokedAt: now,
174
+ revokedBySubject: input.actorSubject,
175
+ });
176
+ return true;
177
+ }
178
+ async loadActiveClient(clientId, now) {
179
+ const principal = this.#principals.get(clientId);
180
+ if (principal === undefined || principal.status !== 'active')
181
+ return undefined;
182
+ validateServicePrincipalEpoch('authorization time', now);
183
+ return {
184
+ principal: clone(principal),
185
+ grants: [...this.#grants.values()]
186
+ .filter((grant) => grant.principalId === clientId && grant.status === 'active')
187
+ .map(clone),
188
+ credentials: [...this.#credentials.values()]
189
+ .filter((credential) => credential.principalId === clientId &&
190
+ servicePrincipalCredentialIsActive(credential, now))
191
+ .map(clone),
192
+ };
193
+ }
194
+ async validateAccessBinding(input) {
195
+ validateServicePrincipalEpoch('authorization time', input.now);
196
+ const principal = this.#principals.get(input.principalId);
197
+ const grant = this.#grants.get(input.grantId);
198
+ const credential = this.#credentials.get(input.credentialId);
199
+ return (principal?.status === 'active' &&
200
+ principal.org === input.org &&
201
+ grant?.status === 'active' &&
202
+ grant.principalId === principal.principalId &&
203
+ grant.org === input.org &&
204
+ grant.app === input.app &&
205
+ grant.environment === input.environment &&
206
+ credential !== undefined &&
207
+ credential.principalId === principal.principalId &&
208
+ servicePrincipalCredentialIsActive(credential, input.now));
209
+ }
210
+ async consumeAssertionJti(input) {
211
+ validateServicePrincipalEpoch('assertion time', input.now);
212
+ validateServicePrincipalEpoch('assertion expiry', input.expiresAt);
213
+ if (input.expiresAt <= input.now)
214
+ throw new Error('assertion expiry must be in the future');
215
+ if (input.jti.length < 1 || input.jti.length > 200) {
216
+ throw new Error('assertion jti must be between 1 and 200 characters');
217
+ }
218
+ if (!this.#credentials.has(input.credentialId)) {
219
+ throw new Error('assertion credential does not exist');
220
+ }
221
+ for (const [key, expiresAt] of this.#assertionJtis) {
222
+ if (expiresAt <= input.now)
223
+ this.#assertionJtis.delete(key);
224
+ }
225
+ const key = `${input.credentialId}\u0000${input.jti}`;
226
+ if (this.#assertionJtis.has(key))
227
+ return false;
228
+ this.#assertionJtis.set(key, input.expiresAt);
229
+ return true;
230
+ }
231
+ #ownedPrincipal(input, strict) {
232
+ const org = validateSlug('org', input.org);
233
+ const principal = this.#principals.get(input.principalId);
234
+ if (principal === undefined || principal.org === org)
235
+ return principal;
236
+ if (strict)
237
+ throw new Error('service principal belongs to a different organization');
238
+ return undefined;
239
+ }
240
+ #requireActivePrincipal(input) {
241
+ const principal = this.#ownedPrincipal(input, true);
242
+ if (principal === undefined)
243
+ throw new Error('service principal does not exist');
244
+ if (principal.status !== 'active')
245
+ throw new Error('service principal is revoked');
246
+ return principal;
247
+ }
248
+ }
249
+ export function publicServicePrincipalCredential(credential) {
250
+ const { credentialId, principalId, kind, label, status, createdBySubject, createdAt, updatedAt } = credential;
251
+ const lifecycle = {
252
+ credentialId,
253
+ principalId,
254
+ kind,
255
+ label,
256
+ status,
257
+ createdBySubject,
258
+ createdAt,
259
+ updatedAt,
260
+ ...(credential.expiresAt === undefined ? {} : { expiresAt: credential.expiresAt }),
261
+ ...(credential.revokedAt === undefined
262
+ ? {}
263
+ : {
264
+ revokedAt: credential.revokedAt,
265
+ ...(credential.revokedBySubject === undefined
266
+ ? {}
267
+ : { revokedBySubject: credential.revokedBySubject }),
268
+ }),
269
+ };
270
+ return credential.kind === 'public_jwk'
271
+ ? {
272
+ ...lifecycle,
273
+ kind: 'public_jwk',
274
+ algorithm: credential.algorithm,
275
+ ...(credential.kid === undefined ? {} : { kid: credential.kid }),
276
+ }
277
+ : { ...lifecycle, kind: 'client_secret' };
278
+ }
279
+ export function normalizeServicePrincipalScopes(values) {
280
+ const normalized = [...new Set(values.map(validateScope))].sort();
281
+ if (normalized.length > 64)
282
+ throw new Error('service-principal grant supports at most 64 scopes');
283
+ return Object.freeze(normalized);
284
+ }
285
+ function validateScope(value) {
286
+ const normalized = value.trim();
287
+ if (normalized.length < 1 ||
288
+ normalized.length > 128 ||
289
+ !/^[\x21\x23-\x5b\x5d-\x7e]+$/.test(normalized)) {
290
+ throw new Error('service-principal scope must be one valid 1-128 character OAuth scope token');
291
+ }
292
+ return normalized;
293
+ }
294
+ export function validateServicePrincipalDisplayName(label, value) {
295
+ const normalized = value.trim();
296
+ if (normalized.length < 1 || normalized.length > 80 || hasAsciiControlCharacters(normalized)) {
297
+ throw new Error(`${label} must be between 1 and 80 printable characters`);
298
+ }
299
+ return normalized;
300
+ }
301
+ export function validateServicePrincipalActor(value) {
302
+ if (value.length < 1 || value.length > 512 || hasAsciiControlCharacters(value)) {
303
+ throw new Error('invalid service-principal actor');
304
+ }
305
+ return value;
306
+ }
307
+ export function validateServicePrincipalSecretDigest(value) {
308
+ if (!/^[A-Za-z0-9_-]{43}$/.test(value) || Buffer.from(value, 'base64url').length !== 32) {
309
+ throw new Error('service-principal secret digest must be a SHA-256 base64url value');
310
+ }
311
+ return value;
312
+ }
313
+ export function normalizeServicePrincipalExpiry(value, now) {
314
+ if (value === undefined)
315
+ return undefined;
316
+ const parsed = new Date(value);
317
+ if (!Number.isFinite(parsed.getTime()) || parsed.getTime() <= now.getTime()) {
318
+ throw new Error('service-principal credential expiresAt must be a future ISO timestamp');
319
+ }
320
+ return parsed.toISOString();
321
+ }
322
+ export function servicePrincipalCredentialIsActive(credential, now) {
323
+ return (credential.status === 'active' &&
324
+ (credential.expiresAt === undefined || Date.parse(credential.expiresAt) > now));
325
+ }
326
+ export function currentServicePrincipalDate(now) {
327
+ const value = now();
328
+ if (!Number.isFinite(value.getTime()))
329
+ throw new Error('service-principal store clock is invalid');
330
+ return value;
331
+ }
332
+ export function currentServicePrincipalTimestamp(now) {
333
+ return currentServicePrincipalDate(now).toISOString();
334
+ }
335
+ export function validateServicePrincipalEpoch(label, value) {
336
+ if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
337
+ throw new Error(`${label} must be a non-negative integer epoch millisecond`);
338
+ }
339
+ }
340
+ function hasAsciiControlCharacters(value) {
341
+ return [...value].some((character) => {
342
+ const code = character.charCodeAt(0);
343
+ return code <= 0x1f || code === 0x7f;
344
+ });
345
+ }
346
+ function clone(value) {
347
+ return structuredClone(value);
348
+ }
349
+ //# sourceMappingURL=service-principal-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-principal-store.js","sourceRoot":"","sources":["../../src/oauth/service-principal-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { AuditSink } from '@noodle-borg/module';
2
+ import type { Request, Response } from 'express';
3
+ import type { ServerRegistry } from '../registry.js';
4
+ import { type ServicePrincipalResourceRouting } from './service-principal-resource.js';
5
+ import type { ServicePrincipalRuntime } from './service-principal-store.js';
6
+ import type { IssueServicePrincipalAccessTokenInput } from './service-principal-token-issuer.js';
7
+ export interface ServicePrincipalTokenIssuer {
8
+ readonly issuer: string;
9
+ nowSeconds(): number;
10
+ issueServicePrincipalAccessToken(input: IssueServicePrincipalAccessTokenInput): Promise<string>;
11
+ }
12
+ export interface ServicePrincipalTokenHandlerOptions {
13
+ readonly runtime: ServicePrincipalRuntime;
14
+ readonly registry: () => ServerRegistry | undefined;
15
+ readonly routing: ServicePrincipalResourceRouting;
16
+ readonly audit?: AuditSink;
17
+ }
18
+ /** Handle only the OAuth client_credentials grant; the caller owns grant-type dispatch. */
19
+ export declare function handleServicePrincipalToken(req: Request, res: Response, issuer: ServicePrincipalTokenIssuer, options: ServicePrincipalTokenHandlerOptions): Promise<void>;
20
+ //# sourceMappingURL=service-principal-token-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-principal-token-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/service-principal-token-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD,OAAO,EAGL,KAAK,+BAA+B,EACrC,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAGV,uBAAuB,EACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAIjG,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,UAAU,IAAI,MAAM,CAAC;IACrB,gCAAgC,CAAC,KAAK,EAAE,qCAAqC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjG;AAED,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,cAAc,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAAC;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,2FAA2F;AAC3F,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,2BAA2B,EACnC,OAAO,EAAE,mCAAmC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAwIf"}
@@ -0,0 +1,175 @@
1
+ import { authenticateServicePrincipalClient, ServicePrincipalClientAuthError, } from './service-principal-client-auth.js';
2
+ import { resolveServicePrincipalResource, } from './service-principal-resource.js';
3
+ const TEN_MINUTES = 600;
4
+ /** Handle only the OAuth client_credentials grant; the caller owns grant-type dispatch. */
5
+ export async function handleServicePrincipalToken(req, res, issuer, options) {
6
+ noStore(res);
7
+ if (!options.runtime.ready) {
8
+ oauthError(res, 503, 'temporarily_unavailable', 'service-principal authentication is unavailable');
9
+ return;
10
+ }
11
+ const nowSeconds = issuer.nowSeconds();
12
+ let client;
13
+ try {
14
+ const authorization = authorizationHeaders(req);
15
+ client = await authenticateServicePrincipalClient({ body: body(req), ...(authorization === undefined ? {} : { authorization }) }, options.runtime.store, `${issuer.issuer.replace(/\/+$/, '')}/token`, nowSeconds);
16
+ }
17
+ catch (error) {
18
+ if (error instanceof ServicePrincipalClientAuthError) {
19
+ res.setHeader('WWW-Authenticate', 'Basic realm="token"');
20
+ oauthError(res, 401, error.oauthError, error.message);
21
+ return;
22
+ }
23
+ oauthError(res, 401, 'invalid_client', 'invalid client authentication');
24
+ return;
25
+ }
26
+ const resource = oneRequiredString(body(req).resource);
27
+ if (resource === undefined) {
28
+ oauthError(res, 400, 'invalid_request', 'exactly one resource parameter is required');
29
+ return;
30
+ }
31
+ const registry = options.registry();
32
+ if (registry === undefined) {
33
+ oauthError(res, 400, 'invalid_target', 'requested resource is unavailable');
34
+ return;
35
+ }
36
+ let resolved;
37
+ try {
38
+ resolved = await resolveServicePrincipalResource(resource, registry, options.routing);
39
+ }
40
+ catch {
41
+ oauthError(res, 400, 'invalid_target', 'requested resource is unavailable');
42
+ return;
43
+ }
44
+ if (resolved === undefined || resolved.tenant.org !== client.org) {
45
+ oauthError(res, 400, 'invalid_target', 'requested resource is unavailable');
46
+ return;
47
+ }
48
+ let activeClient;
49
+ try {
50
+ activeClient = await options.runtime.store.loadActiveClient(client.principalId, nowSeconds * 1000);
51
+ }
52
+ catch {
53
+ oauthError(res, 401, 'invalid_client', 'invalid client authentication');
54
+ return;
55
+ }
56
+ const grant = matchingGrant(activeClient?.grants ?? [], resolved.tenant);
57
+ if (grant === undefined) {
58
+ oauthError(res, 400, 'invalid_target', 'requested resource is unavailable');
59
+ return;
60
+ }
61
+ const scopes = requestedScopes(body(req).scope, grant.scopes);
62
+ if (scopes === undefined) {
63
+ oauthError(res, 400, 'invalid_scope', 'requested scope is invalid');
64
+ return;
65
+ }
66
+ try {
67
+ const bindingIsLive = await options.runtime.store.validateAccessBinding({
68
+ principalId: client.principalId,
69
+ grantId: grant.grantId,
70
+ credentialId: client.credentialId,
71
+ org: resolved.tenant.org,
72
+ app: resolved.tenant.app,
73
+ environment: resolved.tenant.env,
74
+ now: nowSeconds * 1000,
75
+ });
76
+ if (!bindingIsLive) {
77
+ oauthError(res, 401, 'invalid_client', 'invalid client authentication');
78
+ return;
79
+ }
80
+ if (client.assertion !== undefined) {
81
+ const consumed = await options.runtime.store.consumeAssertionJti({
82
+ credentialId: client.credentialId,
83
+ jti: client.assertion.jti,
84
+ expiresAt: client.assertion.expiresAt * 1000,
85
+ now: nowSeconds * 1000,
86
+ });
87
+ if (!consumed) {
88
+ oauthError(res, 401, 'invalid_client', 'invalid client authentication');
89
+ return;
90
+ }
91
+ }
92
+ const scope = scopes.join(' ');
93
+ const accessToken = await issuer.issueServicePrincipalAccessToken({
94
+ principalId: client.principalId,
95
+ resource: resolved.resource,
96
+ ...(scope.length === 0 ? {} : { scope }),
97
+ grantId: grant.grantId,
98
+ credentialId: client.credentialId,
99
+ ttlSeconds: TEN_MINUTES,
100
+ });
101
+ await options.audit?.emit({
102
+ eventType: 'service_principal.token.issued',
103
+ org: resolved.tenant.org,
104
+ app: resolved.tenant.app,
105
+ env: resolved.tenant.env,
106
+ ...(resolved.deploymentId === undefined ? {} : { deploymentId: resolved.deploymentId }),
107
+ actorSubject: client.principalId,
108
+ decision: 'allow',
109
+ status: 200,
110
+ details: {
111
+ principalId: client.principalId,
112
+ grantId: grant.grantId,
113
+ credentialId: client.credentialId,
114
+ },
115
+ });
116
+ res.status(200).json({
117
+ access_token: accessToken,
118
+ token_type: 'Bearer',
119
+ expires_in: TEN_MINUTES,
120
+ ...(scope.length === 0 ? {} : { scope }),
121
+ });
122
+ }
123
+ catch {
124
+ oauthError(res, 401, 'invalid_client', 'invalid client authentication');
125
+ }
126
+ }
127
+ function body(req) {
128
+ return req.body !== null && typeof req.body === 'object'
129
+ ? req.body
130
+ : {};
131
+ }
132
+ function authorizationHeaders(req) {
133
+ const values = [];
134
+ for (let index = 0; index < req.rawHeaders.length; index += 2) {
135
+ if (req.rawHeaders[index]?.toLowerCase() === 'authorization') {
136
+ const value = req.rawHeaders[index + 1];
137
+ if (value !== undefined)
138
+ values.push(value);
139
+ }
140
+ }
141
+ if (values.length === 0)
142
+ return undefined;
143
+ return values.length === 1 ? values[0] : values;
144
+ }
145
+ function oneRequiredString(value) {
146
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
147
+ }
148
+ function matchingGrant(grants, tenant) {
149
+ return grants.find((grant) => grant.status === 'active' &&
150
+ grant.org === tenant.org &&
151
+ grant.app === tenant.app &&
152
+ grant.environment === tenant.env);
153
+ }
154
+ function requestedScopes(value, ceiling) {
155
+ if (value === undefined)
156
+ return ceiling;
157
+ if (typeof value !== 'string' || value.length === 0)
158
+ return undefined;
159
+ const scopes = value.split(' ');
160
+ if (scopes.length > 64 ||
161
+ scopes.some((scope) => scope.length < 1 || scope.length > 128 || !/^[\x21\x23-\x5b\x5d-\x7e]+$/.test(scope)) ||
162
+ new Set(scopes).size !== scopes.length) {
163
+ return undefined;
164
+ }
165
+ const allowed = new Set(ceiling);
166
+ return scopes.every((scope) => allowed.has(scope)) ? [...scopes].sort() : undefined;
167
+ }
168
+ function noStore(res) {
169
+ res.setHeader('Cache-Control', 'no-store');
170
+ res.setHeader('Pragma', 'no-cache');
171
+ }
172
+ function oauthError(res, status, error, description) {
173
+ res.status(status).json({ error, error_description: description });
174
+ }
175
+ //# sourceMappingURL=service-principal-token-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-principal-token-handler.js","sourceRoot":"","sources":["../../src/oauth/service-principal-token-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SigningKeyProvider } from '@noodle-borg/auth';
2
+ export interface IssueServicePrincipalAccessTokenInput {
3
+ readonly principalId: string;
4
+ readonly resource: string;
5
+ readonly scope?: string;
6
+ readonly grantId: string;
7
+ readonly credentialId: string;
8
+ readonly ttlSeconds: number;
9
+ }
10
+ /** Mint one service-marked token while keeping private lifecycle bindings out of the public caller. */
11
+ export declare function issueServicePrincipalAccessToken(signer: SigningKeyProvider, issuer: string, input: IssueServicePrincipalAccessTokenInput): Promise<string>;
12
+ //# sourceMappingURL=service-principal-token-issuer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-principal-token-issuer.d.ts","sourceRoot":"","sources":["../../src/oauth/service-principal-token-issuer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,uGAAuG;AACvG,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,qCAAqC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
@@ -0,0 +1,20 @@
1
+ import { mintOAuthAccessToken } from './token-issuer.js';
2
+ /** Mint one service-marked token while keeping private lifecycle bindings out of the public caller. */
3
+ export function issueServicePrincipalAccessToken(signer, issuer, input) {
4
+ return mintOAuthAccessToken({
5
+ signer,
6
+ issuer,
7
+ ttlSeconds: input.ttlSeconds,
8
+ identity: {
9
+ ownerSubject: input.principalId,
10
+ resource: input.resource,
11
+ ...(input.scope === undefined ? {} : { scope: input.scope }),
12
+ roles: [],
13
+ identityKind: 'service',
14
+ oauthClientId: input.principalId,
15
+ servicePrincipalGrantId: input.grantId,
16
+ servicePrincipalCredentialId: input.credentialId,
17
+ },
18
+ });
19
+ }
20
+ //# sourceMappingURL=service-principal-token-issuer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-principal-token-issuer.js","sourceRoot":"","sources":["../../src/oauth/service-principal-token-issuer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAWzD,uGAAuG;AACvG,MAAM,UAAU,gCAAgC,CAC9C,MAA0B,EAC1B,MAAc,EACd,KAA4C;IAE5C,OAAO,oBAAoB,CAAC;QAC1B,MAAM;QACN,MAAM;QACN,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE;YACR,YAAY,EAAE,KAAK,CAAC,WAAW;YAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5D,KAAK,EAAE,EAAE;YACT,YAAY,EAAE,SAAS;YACvB,aAAa,EAAE,KAAK,CAAC,WAAW;YAChC,uBAAuB,EAAE,KAAK,CAAC,OAAO;YACtC,4BAA4B,EAAE,KAAK,CAAC,YAAY;SACjD;KACF,CAAC,CAAC;AACL,CAAC"}