@caronte-sdk/node 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.
Files changed (40) hide show
  1. package/README.md +198 -0
  2. package/dist/adapters/apollo.cjs +71 -0
  3. package/dist/adapters/apollo.cjs.map +1 -0
  4. package/dist/adapters/apollo.d.cts +34 -0
  5. package/dist/adapters/apollo.d.ts +34 -0
  6. package/dist/adapters/apollo.js +45 -0
  7. package/dist/adapters/apollo.js.map +1 -0
  8. package/dist/adapters/express.cjs +57 -0
  9. package/dist/adapters/express.cjs.map +1 -0
  10. package/dist/adapters/express.d.cts +19 -0
  11. package/dist/adapters/express.d.ts +19 -0
  12. package/dist/adapters/express.js +41 -0
  13. package/dist/adapters/express.js.map +1 -0
  14. package/dist/adapters/fastify.cjs +66 -0
  15. package/dist/adapters/fastify.cjs.map +1 -0
  16. package/dist/adapters/fastify.d.cts +19 -0
  17. package/dist/adapters/fastify.d.ts +19 -0
  18. package/dist/adapters/fastify.js +42 -0
  19. package/dist/adapters/fastify.js.map +1 -0
  20. package/dist/adapters/nest/index.cjs +299 -0
  21. package/dist/adapters/nest/index.cjs.map +1 -0
  22. package/dist/adapters/nest/index.d.cts +60 -0
  23. package/dist/adapters/nest/index.d.ts +60 -0
  24. package/dist/adapters/nest/index.js +109 -0
  25. package/dist/adapters/nest/index.js.map +1 -0
  26. package/dist/chunk-AKUM2UEO.js +21 -0
  27. package/dist/chunk-AKUM2UEO.js.map +1 -0
  28. package/dist/chunk-G73YTEJQ.js +146 -0
  29. package/dist/chunk-G73YTEJQ.js.map +1 -0
  30. package/dist/chunk-HV6X5RJY.js +37 -0
  31. package/dist/chunk-HV6X5RJY.js.map +1 -0
  32. package/dist/client-Cgm1csuM.d.cts +49 -0
  33. package/dist/client-Cgm1csuM.d.ts +49 -0
  34. package/dist/index.cjs +199 -0
  35. package/dist/index.cjs.map +1 -0
  36. package/dist/index.d.cts +27 -0
  37. package/dist/index.d.ts +27 -0
  38. package/dist/index.js +5 -0
  39. package/dist/index.js.map +1 -0
  40. package/package.json +78 -0
@@ -0,0 +1,19 @@
1
+ import { FastifyReply, FastifyPluginAsync } from 'fastify';
2
+ import { T as TokenClaims, A as ArgosClient } from '../client-Cgm1csuM.cjs';
3
+
4
+ interface ArgosPluginOptions {
5
+ client: ArgosClient;
6
+ }
7
+ declare const argosFastifyPlugin: FastifyPluginAsync<ArgosPluginOptions>;
8
+ declare module 'fastify' {
9
+ interface FastifyRequest {
10
+ argosUser?: TokenClaims;
11
+ }
12
+ }
13
+ declare module 'fastify' {
14
+ interface FastifyInstance {
15
+ argosGuard: (id: string, level: string, method?: string) => (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
16
+ }
17
+ }
18
+
19
+ export { type ArgosPluginOptions, argosFastifyPlugin };
@@ -0,0 +1,19 @@
1
+ import { FastifyReply, FastifyPluginAsync } from 'fastify';
2
+ import { T as TokenClaims, A as ArgosClient } from '../client-Cgm1csuM.js';
3
+
4
+ interface ArgosPluginOptions {
5
+ client: ArgosClient;
6
+ }
7
+ declare const argosFastifyPlugin: FastifyPluginAsync<ArgosPluginOptions>;
8
+ declare module 'fastify' {
9
+ interface FastifyRequest {
10
+ argosUser?: TokenClaims;
11
+ }
12
+ }
13
+ declare module 'fastify' {
14
+ interface FastifyInstance {
15
+ argosGuard: (id: string, level: string, method?: string) => (req: FastifyRequest, reply: FastifyReply) => Promise<void>;
16
+ }
17
+ }
18
+
19
+ export { type ArgosPluginOptions, argosFastifyPlugin };
@@ -0,0 +1,42 @@
1
+ import { detectMethod, registerOperation } from '../chunk-HV6X5RJY.js';
2
+ import fp from 'fastify-plugin';
3
+
4
+ var argosPlugin = async (fastify, { client }) => {
5
+ fastify.decorateRequest("argosUser", void 0);
6
+ fastify.addHook("onRequest", async (request) => {
7
+ const auth = request.headers.authorization ?? "";
8
+ const [scheme, token] = auth.split(" ");
9
+ if (scheme?.toLowerCase() === "bearer" && token) {
10
+ try {
11
+ request.argosUser = await client.validateToken(token);
12
+ } catch {
13
+ }
14
+ }
15
+ });
16
+ fastify.decorate(
17
+ "argosGuard",
18
+ (id, level, method) => {
19
+ const resolvedMethod = method ?? detectMethod(id);
20
+ registerOperation({ identifier: id, method: resolvedMethod, level });
21
+ return async (request, reply) => {
22
+ if (level === "public") return;
23
+ if (!request.argosUser) {
24
+ await reply.status(401).send({ error: "unauthorized", detail: "Bearer token required." });
25
+ return;
26
+ }
27
+ const allowed = client.checkPermission(request.argosUser, id, resolvedMethod);
28
+ if (!allowed) {
29
+ await reply.status(403).send({ error: "forbidden", detail: "Insufficient permissions." });
30
+ }
31
+ };
32
+ }
33
+ );
34
+ };
35
+ var argosFastifyPlugin = fp(argosPlugin, {
36
+ name: "argos",
37
+ fastify: ">=4"
38
+ });
39
+
40
+ export { argosFastifyPlugin };
41
+ //# sourceMappingURL=fastify.js.map
42
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/fastify.ts"],"names":[],"mappings":";;;AAgBA,IAAM,WAAA,GAAsD,OAC1D,OAAA,EACA,EAAE,QAAO,KACN;AAEH,EAAA,OAAA,CAAQ,eAAA,CAAyC,aAAa,MAAS,CAAA;AAGvE,EAAA,OAAA,CAAQ,OAAA,CAAQ,WAAA,EAAa,OAAO,OAAA,KAA4B;AAC9D,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,aAAA,IAAiB,EAAA;AAC9C,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AACtC,IAAA,IAAI,MAAA,EAAQ,WAAA,EAAY,KAAM,QAAA,IAAY,KAAA,EAAO;AAC/C,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,MAAA,CAAO,aAAA,CAAc,KAAK,CAAA;AAAA,MACtD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAGD,EAAA,OAAA,CAAQ,QAAA;AAAA,IACN,YAAA;AAAA,IACA,CAAC,EAAA,EAAY,KAAA,EAAe,MAAA,KAAoB;AAC9C,MAAA,MAAM,cAAA,GAAiB,MAAA,IAAU,YAAA,CAAa,EAAE,CAAA;AAChD,MAAA,iBAAA,CAAkB,EAAE,UAAA,EAAY,EAAA,EAAI,MAAA,EAAQ,cAAA,EAAgB,OAAO,CAAA;AAEnE,MAAA,OAAO,OAAO,SAAyB,KAAA,KAAuC;AAC5E,QAAA,IAAI,UAAU,QAAA,EAAU;AAExB,QAAA,IAAI,CAAC,QAAQ,SAAA,EAAW;AACtB,UAAA,MAAM,KAAA,CAAM,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,MAAA,EAAQ,wBAAA,EAA0B,CAAA;AACxF,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,UAAU,MAAA,CAAO,eAAA,CAAgB,OAAA,CAAQ,SAAA,EAAW,IAAI,cAAc,CAAA;AAC5E,QAAA,IAAI,CAAC,OAAA,EAAS;AACZ,UAAA,MAAM,KAAA,CAAM,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,EAAE,KAAA,EAAO,WAAA,EAAa,MAAA,EAAQ,2BAAA,EAA6B,CAAA;AAAA,QAC1F;AAAA,MACF,CAAA;AAAA,IACF;AAAA,GACF;AACF,CAAA;AAEO,IAAM,kBAAA,GAAqB,GAAG,WAAA,EAAa;AAAA,EAChD,IAAA,EAAM,OAAA;AAAA,EACN,OAAA,EAAS;AACX,CAAC","file":"fastify.js","sourcesContent":["import type { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify';\nimport fp from 'fastify-plugin';\nimport { ArgosClient } from '../client.js';\nimport type { TokenClaims } from '../models.js';\nimport { detectMethod, registerOperation } from '../registry.js';\n\ndeclare module 'fastify' {\n interface FastifyRequest {\n argosUser?: TokenClaims;\n }\n}\n\nexport interface ArgosPluginOptions {\n client: ArgosClient;\n}\n\nconst argosPlugin: FastifyPluginAsync<ArgosPluginOptions> = async (\n fastify: FastifyInstance,\n { client }: ArgosPluginOptions,\n) => {\n // Decorate request with argosUser\n fastify.decorateRequest<TokenClaims | undefined>('argosUser', undefined);\n\n // Global hook — validates Bearer token on every request\n fastify.addHook('onRequest', async (request: FastifyRequest) => {\n const auth = request.headers.authorization ?? '';\n const [scheme, token] = auth.split(' ');\n if (scheme?.toLowerCase() === 'bearer' && token) {\n try {\n request.argosUser = await client.validateToken(token);\n } catch {\n // invalid token — argosUser stays null; guard handles the 401\n }\n }\n });\n\n // Decorate fastify with a guard factory\n fastify.decorate(\n 'argosGuard',\n (id: string, level: string, method?: string) => {\n const resolvedMethod = method ?? detectMethod(id);\n registerOperation({ identifier: id, method: resolvedMethod, level });\n\n return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {\n if (level === 'public') return;\n\n if (!request.argosUser) {\n await reply.status(401).send({ error: 'unauthorized', detail: 'Bearer token required.' });\n return;\n }\n\n const allowed = client.checkPermission(request.argosUser, id, resolvedMethod);\n if (!allowed) {\n await reply.status(403).send({ error: 'forbidden', detail: 'Insufficient permissions.' });\n }\n };\n },\n );\n};\n\nexport const argosFastifyPlugin = fp(argosPlugin, {\n name: 'argos',\n fastify: '>=4',\n});\n\ndeclare module 'fastify' {\n interface FastifyInstance {\n argosGuard: (\n id: string,\n level: string,\n method?: string,\n ) => (req: FastifyRequest, reply: FastifyReply) => Promise<void>;\n }\n}"]}
@@ -0,0 +1,299 @@
1
+ 'use strict';
2
+
3
+ var common = require('@nestjs/common');
4
+ var core = require('@nestjs/core');
5
+ var jose = require('jose');
6
+
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
+ var __decorateClass = (decorators, target, key, kind) => {
9
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
10
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
11
+ if (decorator = decorators[i])
12
+ result = (decorator(result)) || result;
13
+ return result;
14
+ };
15
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
16
+
17
+ // src/registry.ts
18
+ var _registry = [];
19
+ function detectMethod(id) {
20
+ const last = (id.split(":").pop() ?? "").toLowerCase();
21
+ if (/^(get|list|fetch|read)/.test(last)) return "read";
22
+ if (/^(delete|remove|destroy)/.test(last)) return "delete";
23
+ if (/(stream|subscribe|watch|listen)/.test(last)) return "stream";
24
+ return "write";
25
+ }
26
+ function registerOperation(op) {
27
+ const exists = _registry.some(
28
+ (o) => o.identifier === op.identifier && o.method === op.method
29
+ );
30
+ if (!exists) _registry.push(op);
31
+ }
32
+ function getRegistry() {
33
+ return [..._registry];
34
+ }
35
+
36
+ // src/adapters/nest/decorator.ts
37
+ var OPERATION_KEY = "argos:operation";
38
+ function Operation(id, level, method) {
39
+ const resolvedMethod = method ?? detectMethod(id);
40
+ registerOperation({ identifier: id, method: resolvedMethod, level });
41
+ return common.SetMetadata(OPERATION_KEY, { id, level, method: resolvedMethod });
42
+ }
43
+ var ArgosUser = common.createParamDecorator(
44
+ (_data, ctx) => ctx.switchToHttp().getRequest().argosUser
45
+ );
46
+
47
+ // src/exceptions.ts
48
+ var ArgosError = class extends Error {
49
+ constructor(message) {
50
+ super(message);
51
+ this.name = this.constructor.name;
52
+ }
53
+ };
54
+ var ArgosAuthError = class extends ArgosError {
55
+ };
56
+ var ArgosTokenError = class extends ArgosError {
57
+ };
58
+ var ArgosSyncError = class extends ArgosError {
59
+ };
60
+ var ArgosConfigError = class extends ArgosError {
61
+ };
62
+
63
+ // src/client.ts
64
+ var ArgosClient = class _ArgosClient {
65
+ base;
66
+ realmId;
67
+ appId;
68
+ secret;
69
+ appToken = null;
70
+ jwks = null;
71
+ operations = [];
72
+ registeredOperations = [];
73
+ constructor(options) {
74
+ this.base = options.authorizerUrl.replace(/\/$/, "");
75
+ this.realmId = options.realmId;
76
+ this.appId = options.appId;
77
+ this.secret = options.secret;
78
+ }
79
+ get realmBase() {
80
+ return `${this.base}/realms/${this.realmId}`;
81
+ }
82
+ registerOperation(op) {
83
+ this.registeredOperations.push(op);
84
+ }
85
+ async startup() {
86
+ if (this.registeredOperations.length === 0) {
87
+ throw new ArgosConfigError(
88
+ "No operations registered. Call registerOperation() before startup()."
89
+ );
90
+ }
91
+ await this.authenticate();
92
+ this.initJwks();
93
+ await this.syncOperations();
94
+ await this.fetchOperations();
95
+ }
96
+ async authenticate() {
97
+ const res = await fetch(`${this.realmBase}/apps/token`, {
98
+ method: "POST",
99
+ headers: { "Content-Type": "application/json" },
100
+ body: JSON.stringify({ app_id: this.appId, secret: this.secret })
101
+ });
102
+ if (!res.ok) {
103
+ throw new ArgosAuthError(
104
+ `Authentication failed: HTTP ${res.status} \u2014 ${await res.text()}`
105
+ );
106
+ }
107
+ const data = await res.json();
108
+ if (!data.access_token) throw new ArgosAuthError("Authorizer returned no access_token.");
109
+ this.appToken = data.access_token;
110
+ }
111
+ initJwks() {
112
+ this.jwks = jose.createRemoteJWKSet(
113
+ new URL(`${this.realmBase}/protocol/openid-connect/certs`)
114
+ );
115
+ }
116
+ async syncOperations() {
117
+ this.ensureAppToken();
118
+ const res = await fetch(`${this.realmBase}/apps/operations/sync`, {
119
+ method: "POST",
120
+ headers: {
121
+ "Content-Type": "application/json",
122
+ Authorization: `Bearer ${this.appToken}`
123
+ },
124
+ body: JSON.stringify({
125
+ operations: this.registeredOperations.map((op) => ({
126
+ identifier: op.identifier,
127
+ method: op.method,
128
+ level: op.level,
129
+ description: op.description ?? null
130
+ }))
131
+ })
132
+ });
133
+ if (!res.ok) {
134
+ throw new ArgosSyncError(`Sync failed: HTTP ${res.status} \u2014 ${await res.text()}`);
135
+ }
136
+ }
137
+ async fetchOperations() {
138
+ this.ensureAppToken();
139
+ const res = await fetch(`${this.realmBase}/apps/operations`, {
140
+ headers: { Authorization: `Bearer ${this.appToken}` }
141
+ });
142
+ if (!res.ok) {
143
+ throw new ArgosError(
144
+ `Fetch operations failed: HTTP ${res.status} \u2014 ${await res.text()}`
145
+ );
146
+ }
147
+ const data = await res.json();
148
+ this.operations = data.operations.map((op) => ({
149
+ operationId: op.operation_id,
150
+ identifier: op.identifier,
151
+ method: op.method,
152
+ level: op.level,
153
+ allowedGroups: op.allowed_groups ?? []
154
+ }));
155
+ }
156
+ async validateToken(token) {
157
+ if (!this.jwks) this.initJwks();
158
+ try {
159
+ const { payload } = await jose.jwtVerify(token, this.jwks);
160
+ const p = payload;
161
+ const tokenRealm = p["realm_id"] ?? "";
162
+ if (tokenRealm.toLowerCase() !== this.realmId.toLowerCase()) {
163
+ throw new ArgosTokenError(
164
+ `Token realm '${tokenRealm}' does not match this app's realm '${this.realmId}'.`
165
+ );
166
+ }
167
+ return {
168
+ sub: payload.sub ?? "",
169
+ realmId: tokenRealm,
170
+ groups: p["groups"] ?? [],
171
+ exp: payload.exp ?? 0,
172
+ raw: p
173
+ };
174
+ } catch (err) {
175
+ if (err instanceof ArgosTokenError) throw err;
176
+ throw new ArgosTokenError(`Invalid token: ${err.message}`);
177
+ }
178
+ }
179
+ checkPermission(claims, identifier, method) {
180
+ const op = this.operations.find(
181
+ (o) => o.identifier === identifier && o.method === method
182
+ );
183
+ if (!op) return false;
184
+ if (op.level === "public") return true;
185
+ if (op.level === "private") return claims.groups.length > 0;
186
+ if (op.level === "protected") return claims.groups.some((g) => op.allowedGroups.includes(g));
187
+ return false;
188
+ }
189
+ /** Load operations from the global registry and bootstrap the client. */
190
+ static async create(options) {
191
+ const client = new _ArgosClient(options);
192
+ for (const op of getRegistry()) client.registerOperation(op);
193
+ await client.startup();
194
+ return client;
195
+ }
196
+ ensureAppToken() {
197
+ if (!this.appToken) {
198
+ throw new ArgosAuthError("No app token. Call authenticate() or startup() first.");
199
+ }
200
+ }
201
+ };
202
+
203
+ // src/adapters/nest/guard.ts
204
+ exports.ArgosGuard = class ArgosGuard {
205
+ // @Inject() explícito -- não depender de emitDecoratorMetadata (design:paramtypes)
206
+ // pra resolver os parâmetros: o build desta lib usa tsup/esbuild, que não emite
207
+ // essa metadata (limitação conhecida do esbuild), então a injeção implícita por
208
+ // tipo do Nest falha silenciosamente (reflector fica undefined em runtime,
209
+ // TypeError em qualquer rota guardada por ArgosGuard).
210
+ constructor(client, reflector) {
211
+ this.client = client;
212
+ this.reflector = reflector;
213
+ }
214
+ client;
215
+ reflector;
216
+ async canActivate(ctx) {
217
+ const meta = this.reflector.get(
218
+ OPERATION_KEY,
219
+ ctx.getHandler()
220
+ );
221
+ if (!meta) return true;
222
+ const { id, level, method } = meta;
223
+ const request = ctx.switchToHttp().getRequest();
224
+ if (level === "public") return true;
225
+ const auth = request.headers["authorization"] ?? "";
226
+ const [scheme, token] = auth.split(" ");
227
+ if (scheme?.toLowerCase() !== "bearer" || !token) {
228
+ throw new common.UnauthorizedException("Bearer token required.");
229
+ }
230
+ let claims;
231
+ try {
232
+ claims = await this.client.validateToken(token);
233
+ } catch {
234
+ throw new common.UnauthorizedException("Invalid token.");
235
+ }
236
+ request.argosUser = claims;
237
+ const allowed = this.client.checkPermission(claims, id, method);
238
+ if (!allowed) throw new common.ForbiddenException("Insufficient permissions.");
239
+ return true;
240
+ }
241
+ };
242
+ exports.ArgosGuard = __decorateClass([
243
+ common.Injectable(),
244
+ __decorateParam(0, common.Inject(ArgosClient)),
245
+ __decorateParam(1, common.Inject(core.Reflector))
246
+ ], exports.ArgosGuard);
247
+ exports.ArgosModule = class ArgosModule {
248
+ /**
249
+ * Register the argos module globally.
250
+ *
251
+ * Creates the `ArgosClient`, bootstraps it (authenticate + sync + fetch),
252
+ * and provides `ArgosGuard` for injection.
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * // app.module.ts
257
+ * @Module({
258
+ * imports: [
259
+ * ArgosModule.forRootAsync({
260
+ * authorizerUrl: process.env.AUTHORIZER_URL!,
261
+ * realmId: process.env.REALM_ID!,
262
+ * appId: process.env.APP_ID!,
263
+ * secret: process.env.APP_SECRET!,
264
+ * }),
265
+ * ],
266
+ * })
267
+ * export class AppModule {}
268
+ * ```
269
+ */
270
+ static forRootAsync(options) {
271
+ return {
272
+ module: exports.ArgosModule,
273
+ global: true,
274
+ providers: [
275
+ core.Reflector,
276
+ {
277
+ provide: ArgosClient,
278
+ useFactory: async () => {
279
+ const client = new ArgosClient(options);
280
+ for (const op of getRegistry()) client.registerOperation(op);
281
+ await client.startup();
282
+ return client;
283
+ }
284
+ },
285
+ exports.ArgosGuard
286
+ ],
287
+ exports: [ArgosClient, exports.ArgosGuard]
288
+ };
289
+ }
290
+ };
291
+ exports.ArgosModule = __decorateClass([
292
+ common.Module({})
293
+ ], exports.ArgosModule);
294
+
295
+ exports.ArgosUser = ArgosUser;
296
+ exports.OPERATION_KEY = OPERATION_KEY;
297
+ exports.Operation = Operation;
298
+ //# sourceMappingURL=index.cjs.map
299
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/registry.ts","../../../src/adapters/nest/decorator.ts","../../../src/exceptions.ts","../../../src/client.ts","../../../src/adapters/nest/guard.ts","../../../src/adapters/nest/module.ts"],"names":["SetMetadata","createParamDecorator","createRemoteJWKSet","jwtVerify","ArgosGuard","UnauthorizedException","ForbiddenException","Injectable","Reflector","ArgosModule","Module"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { OperationDescriptor } from './models.js';\n\nconst _registry: OperationDescriptor[] = [];\n\n/** Infer operation method from the last segment of the operation id.\n * e.g. \"tasks:list\" → \"read\", \"tasks:create\" → \"write\", \"tasks:delete\" → \"delete\"\n */\nexport function detectMethod(id: string): string {\n const last = (id.split(':').pop() ?? '').toLowerCase();\n if (/^(get|list|fetch|read)/.test(last)) return 'read';\n if (/^(delete|remove|destroy)/.test(last)) return 'delete';\n if (/(stream|subscribe|watch|listen)/.test(last)) return 'stream';\n return 'write';\n}\n\n/** Register an operation in the global registry (used by startup to sync). */\nexport function registerOperation(op: OperationDescriptor): void {\n const exists = _registry.some(\n o => o.identifier === op.identifier && o.method === op.method,\n );\n if (!exists) _registry.push(op);\n}\n\nexport function getRegistry(): OperationDescriptor[] {\n return [..._registry];\n}\n\nexport function clearRegistry(): void {\n _registry.length = 0;\n}","import { createParamDecorator, ExecutionContext, SetMetadata } from '@nestjs/common';\nimport type { TokenClaims } from '../../models.js';\nimport { detectMethod, registerOperation } from '../../registry.js';\n\nexport const OPERATION_KEY = 'argos:operation';\n\nexport interface OperationMeta {\n id: string;\n level: string;\n method: string;\n}\n\n/**\n * Marks a controller method as a argos operation.\n *\n * @example\n * ```ts\n * @Get()\n * @Operation('tasks:list', 'private')\n * listTasks(@ArgosUser() user: TokenClaims) { ... }\n * ```\n */\nexport function Operation(id: string, level: string, method?: string): MethodDecorator {\n const resolvedMethod = method ?? detectMethod(id);\n registerOperation({ identifier: id, method: resolvedMethod, level });\n return SetMetadata<string, OperationMeta>(OPERATION_KEY, { id, level, method: resolvedMethod });\n}\n\n/** Injects the authenticated user's TokenClaims into a parameter. */\nexport const ArgosUser = createParamDecorator(\n (_data: unknown, ctx: ExecutionContext): TokenClaims | undefined =>\n ctx.switchToHttp().getRequest().argosUser,\n);","export class ArgosError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\nexport class ArgosAuthError extends ArgosError {}\nexport class ArgosTokenError extends ArgosError {}\nexport class ArgosForbiddenError extends ArgosError {}\nexport class ArgosSyncError extends ArgosError {}\nexport class ArgosConfigError extends ArgosError {}","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport {\n ArgosAuthError, ArgosConfigError, ArgosError,\n ArgosSyncError, ArgosTokenError,\n} from './exceptions.js';\nimport type { OperationDescriptor, OperationWithGroups, TokenClaims } from './models.js';\nimport { getRegistry } from './registry.js';\n\nexport interface ArgosClientOptions {\n authorizerUrl: string;\n realmId: string;\n appId: string;\n secret: string;\n}\n\nexport class ArgosClient {\n private readonly base: string;\n private readonly realmId: string;\n private readonly appId: string;\n private readonly secret: string;\n\n private appToken: string | null = null;\n private jwks: ReturnType<typeof createRemoteJWKSet> | null = null;\n private operations: OperationWithGroups[] = [];\n private registeredOperations: OperationDescriptor[] = [];\n\n constructor(options: ArgosClientOptions) {\n this.base = options.authorizerUrl.replace(/\\/$/, '');\n this.realmId = options.realmId;\n this.appId = options.appId;\n this.secret = options.secret;\n }\n\n private get realmBase(): string {\n return `${this.base}/realms/${this.realmId}`;\n }\n\n registerOperation(op: OperationDescriptor): void {\n this.registeredOperations.push(op);\n }\n\n async startup(): Promise<void> {\n if (this.registeredOperations.length === 0) {\n throw new ArgosConfigError(\n 'No operations registered. Call registerOperation() before startup().',\n );\n }\n await this.authenticate();\n this.initJwks();\n await this.syncOperations();\n await this.fetchOperations();\n }\n\n async authenticate(): Promise<void> {\n const res = await fetch(`${this.realmBase}/apps/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ app_id: this.appId, secret: this.secret }),\n });\n if (!res.ok) {\n throw new ArgosAuthError(\n `Authentication failed: HTTP ${res.status} — ${await res.text()}`,\n );\n }\n const data = await res.json() as { access_token?: string };\n if (!data.access_token) throw new ArgosAuthError('Authorizer returned no access_token.');\n this.appToken = data.access_token;\n }\n\n private initJwks(): void {\n this.jwks = createRemoteJWKSet(\n new URL(`${this.realmBase}/protocol/openid-connect/certs`),\n );\n }\n\n async syncOperations(): Promise<void> {\n this.ensureAppToken();\n const res = await fetch(`${this.realmBase}/apps/operations/sync`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.appToken}`,\n },\n body: JSON.stringify({\n operations: this.registeredOperations.map(op => ({\n identifier: op.identifier,\n method: op.method,\n level: op.level,\n description: op.description ?? null,\n })),\n }),\n });\n if (!res.ok) {\n throw new ArgosSyncError(`Sync failed: HTTP ${res.status} — ${await res.text()}`);\n }\n }\n\n async fetchOperations(): Promise<void> {\n this.ensureAppToken();\n const res = await fetch(`${this.realmBase}/apps/operations`, {\n headers: { Authorization: `Bearer ${this.appToken}` },\n });\n if (!res.ok) {\n throw new ArgosError(\n `Fetch operations failed: HTTP ${res.status} — ${await res.text()}`,\n );\n }\n const data = await res.json() as { operations: any[] };\n this.operations = data.operations.map(op => ({\n operationId: op.operation_id,\n identifier: op.identifier,\n method: op.method,\n level: op.level,\n allowedGroups: op.allowed_groups ?? [],\n }));\n }\n\n async validateToken(token: string): Promise<TokenClaims> {\n if (!this.jwks) this.initJwks();\n try {\n const { payload } = await jwtVerify(token, this.jwks!);\n const p = payload as JWTPayload & Record<string, unknown>;\n const tokenRealm = (p['realm_id'] as string) ?? '';\n\n // As chaves JWKS já são buscadas em /realms/{this.realmId}/... (ver\n // realmBase), então um token de outro realm normalmente já falharia a\n // verificação de assinatura acima. Esta checagem é defesa em\n // profundidade explícita — não depende desse efeito colateral, e falha\n // com uma mensagem clara em vez de erro de assinatura.\n if (tokenRealm.toLowerCase() !== this.realmId.toLowerCase()) {\n throw new ArgosTokenError(\n `Token realm '${tokenRealm}' does not match this app's realm '${this.realmId}'.`,\n );\n }\n\n return {\n sub: payload.sub ?? '',\n realmId: tokenRealm,\n groups: (p['groups'] as string[]) ?? [],\n exp: payload.exp ?? 0,\n raw: p,\n };\n } catch (err) {\n if (err instanceof ArgosTokenError) throw err;\n throw new ArgosTokenError(`Invalid token: ${(err as Error).message}`);\n }\n }\n\n checkPermission(claims: TokenClaims, identifier: string, method: string): boolean {\n const op = this.operations.find(\n o => o.identifier === identifier && o.method === method,\n );\n if (!op) return false;\n if (op.level === 'public') return true;\n if (op.level === 'private') return claims.groups.length > 0;\n if (op.level === 'protected') return claims.groups.some(g => op.allowedGroups.includes(g));\n return false;\n }\n\n /** Load operations from the global registry and bootstrap the client. */\n static async create(options: ArgosClientOptions): Promise<ArgosClient> {\n const client = new ArgosClient(options);\n for (const op of getRegistry()) client.registerOperation(op);\n await client.startup();\n return client;\n }\n\n private ensureAppToken(): void {\n if (!this.appToken) {\n throw new ArgosAuthError('No app token. Call authenticate() or startup() first.');\n }\n }\n}","import {\n CanActivate, ExecutionContext, ForbiddenException,\n Inject, Injectable, UnauthorizedException,\n} from '@nestjs/common';\nimport { Reflector } from '@nestjs/core';\nimport { ArgosClient } from '../../client.js';\nimport type { TokenClaims } from '../../models.js';\nimport { OPERATION_KEY, type OperationMeta } from './decorator.js';\n\n@Injectable()\nexport class ArgosGuard implements CanActivate {\n // @Inject() explícito -- não depender de emitDecoratorMetadata (design:paramtypes)\n // pra resolver os parâmetros: o build desta lib usa tsup/esbuild, que não emite\n // essa metadata (limitação conhecida do esbuild), então a injeção implícita por\n // tipo do Nest falha silenciosamente (reflector fica undefined em runtime,\n // TypeError em qualquer rota guardada por ArgosGuard).\n constructor(\n @Inject(ArgosClient) private readonly client: ArgosClient,\n @Inject(Reflector) private readonly reflector: Reflector,\n ) {}\n\n async canActivate(ctx: ExecutionContext): Promise<boolean> {\n const meta = this.reflector.get<OperationMeta | undefined>(\n OPERATION_KEY,\n ctx.getHandler(),\n );\n\n if (!meta) return true; // no @Operation — pass through\n\n const { id, level, method } = meta;\n const request = ctx.switchToHttp().getRequest<{ headers: Record<string, string>; argosUser?: TokenClaims }>();\n\n if (level === 'public') return true;\n\n const auth = request.headers['authorization'] ?? '';\n const [scheme, token] = auth.split(' ');\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n throw new UnauthorizedException('Bearer token required.');\n }\n\n let claims: TokenClaims;\n try {\n claims = await this.client.validateToken(token);\n } catch {\n // Token malformado/expirado/inválido -- 401, igual aos adapters express/\n // fastify (que engolem o erro de validateToken pelo mesmo motivo), não\n // deixar virar 500 por exceção não tratada.\n throw new UnauthorizedException('Invalid token.');\n }\n request.argosUser = claims;\n\n const allowed = this.client.checkPermission(claims, id, method);\n if (!allowed) throw new ForbiddenException('Insufficient permissions.');\n\n return true;\n }\n}","import { DynamicModule, Module } from '@nestjs/common';\nimport { Reflector } from '@nestjs/core';\nimport { ArgosClient, type ArgosClientOptions } from '../../client.js';\nimport { getRegistry } from '../../registry.js';\nimport { ArgosGuard } from './guard.js';\n\nexport interface ArgosModuleOptions extends ArgosClientOptions {}\n\n@Module({})\nexport class ArgosModule {\n /**\n * Register the argos module globally.\n *\n * Creates the `ArgosClient`, bootstraps it (authenticate + sync + fetch),\n * and provides `ArgosGuard` for injection.\n *\n * @example\n * ```ts\n * // app.module.ts\n * @Module({\n * imports: [\n * ArgosModule.forRootAsync({\n * authorizerUrl: process.env.AUTHORIZER_URL!,\n * realmId: process.env.REALM_ID!,\n * appId: process.env.APP_ID!,\n * secret: process.env.APP_SECRET!,\n * }),\n * ],\n * })\n * export class AppModule {}\n * ```\n */\n static forRootAsync(options: ArgosModuleOptions): DynamicModule {\n return {\n module: ArgosModule,\n global: true,\n providers: [\n Reflector,\n {\n provide: ArgosClient,\n useFactory: async () => {\n const client = new ArgosClient(options);\n for (const op of getRegistry()) client.registerOperation(op);\n await client.startup();\n return client;\n },\n },\n ArgosGuard,\n ],\n exports: [ArgosClient, ArgosGuard],\n };\n }\n}"]}
@@ -0,0 +1,60 @@
1
+ import { CanActivate, ExecutionContext, DynamicModule } from '@nestjs/common';
2
+ import { Reflector } from '@nestjs/core';
3
+ import { A as ArgosClient, a as ArgosClientOptions } from '../../client-Cgm1csuM.cjs';
4
+
5
+ declare const OPERATION_KEY = "argos:operation";
6
+ interface OperationMeta {
7
+ id: string;
8
+ level: string;
9
+ method: string;
10
+ }
11
+ /**
12
+ * Marks a controller method as a argos operation.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * @Get()
17
+ * @Operation('tasks:list', 'private')
18
+ * listTasks(@ArgosUser() user: TokenClaims) { ... }
19
+ * ```
20
+ */
21
+ declare function Operation(id: string, level: string, method?: string): MethodDecorator;
22
+ /** Injects the authenticated user's TokenClaims into a parameter. */
23
+ declare const ArgosUser: (...dataOrPipes: unknown[]) => ParameterDecorator;
24
+
25
+ declare class ArgosGuard implements CanActivate {
26
+ private readonly client;
27
+ private readonly reflector;
28
+ constructor(client: ArgosClient, reflector: Reflector);
29
+ canActivate(ctx: ExecutionContext): Promise<boolean>;
30
+ }
31
+
32
+ interface ArgosModuleOptions extends ArgosClientOptions {
33
+ }
34
+ declare class ArgosModule {
35
+ /**
36
+ * Register the argos module globally.
37
+ *
38
+ * Creates the `ArgosClient`, bootstraps it (authenticate + sync + fetch),
39
+ * and provides `ArgosGuard` for injection.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * // app.module.ts
44
+ * @Module({
45
+ * imports: [
46
+ * ArgosModule.forRootAsync({
47
+ * authorizerUrl: process.env.AUTHORIZER_URL!,
48
+ * realmId: process.env.REALM_ID!,
49
+ * appId: process.env.APP_ID!,
50
+ * secret: process.env.APP_SECRET!,
51
+ * }),
52
+ * ],
53
+ * })
54
+ * export class AppModule {}
55
+ * ```
56
+ */
57
+ static forRootAsync(options: ArgosModuleOptions): DynamicModule;
58
+ }
59
+
60
+ export { ArgosGuard, ArgosModule, type ArgosModuleOptions, ArgosUser, OPERATION_KEY, Operation, type OperationMeta };
@@ -0,0 +1,60 @@
1
+ import { CanActivate, ExecutionContext, DynamicModule } from '@nestjs/common';
2
+ import { Reflector } from '@nestjs/core';
3
+ import { A as ArgosClient, a as ArgosClientOptions } from '../../client-Cgm1csuM.js';
4
+
5
+ declare const OPERATION_KEY = "argos:operation";
6
+ interface OperationMeta {
7
+ id: string;
8
+ level: string;
9
+ method: string;
10
+ }
11
+ /**
12
+ * Marks a controller method as a argos operation.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * @Get()
17
+ * @Operation('tasks:list', 'private')
18
+ * listTasks(@ArgosUser() user: TokenClaims) { ... }
19
+ * ```
20
+ */
21
+ declare function Operation(id: string, level: string, method?: string): MethodDecorator;
22
+ /** Injects the authenticated user's TokenClaims into a parameter. */
23
+ declare const ArgosUser: (...dataOrPipes: unknown[]) => ParameterDecorator;
24
+
25
+ declare class ArgosGuard implements CanActivate {
26
+ private readonly client;
27
+ private readonly reflector;
28
+ constructor(client: ArgosClient, reflector: Reflector);
29
+ canActivate(ctx: ExecutionContext): Promise<boolean>;
30
+ }
31
+
32
+ interface ArgosModuleOptions extends ArgosClientOptions {
33
+ }
34
+ declare class ArgosModule {
35
+ /**
36
+ * Register the argos module globally.
37
+ *
38
+ * Creates the `ArgosClient`, bootstraps it (authenticate + sync + fetch),
39
+ * and provides `ArgosGuard` for injection.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * // app.module.ts
44
+ * @Module({
45
+ * imports: [
46
+ * ArgosModule.forRootAsync({
47
+ * authorizerUrl: process.env.AUTHORIZER_URL!,
48
+ * realmId: process.env.REALM_ID!,
49
+ * appId: process.env.APP_ID!,
50
+ * secret: process.env.APP_SECRET!,
51
+ * }),
52
+ * ],
53
+ * })
54
+ * export class AppModule {}
55
+ * ```
56
+ */
57
+ static forRootAsync(options: ArgosModuleOptions): DynamicModule;
58
+ }
59
+
60
+ export { ArgosGuard, ArgosModule, type ArgosModuleOptions, ArgosUser, OPERATION_KEY, Operation, type OperationMeta };
@@ -0,0 +1,109 @@
1
+ import { ArgosClient } from '../../chunk-G73YTEJQ.js';
2
+ import '../../chunk-AKUM2UEO.js';
3
+ import { __decorateClass, __decorateParam, getRegistry, detectMethod, registerOperation } from '../../chunk-HV6X5RJY.js';
4
+ import { createParamDecorator, Injectable, Inject, Module, UnauthorizedException, ForbiddenException, SetMetadata } from '@nestjs/common';
5
+ import { Reflector } from '@nestjs/core';
6
+
7
+ var OPERATION_KEY = "argos:operation";
8
+ function Operation(id, level, method) {
9
+ const resolvedMethod = method ?? detectMethod(id);
10
+ registerOperation({ identifier: id, method: resolvedMethod, level });
11
+ return SetMetadata(OPERATION_KEY, { id, level, method: resolvedMethod });
12
+ }
13
+ var ArgosUser = createParamDecorator(
14
+ (_data, ctx) => ctx.switchToHttp().getRequest().argosUser
15
+ );
16
+ var ArgosGuard = class {
17
+ // @Inject() explícito -- não depender de emitDecoratorMetadata (design:paramtypes)
18
+ // pra resolver os parâmetros: o build desta lib usa tsup/esbuild, que não emite
19
+ // essa metadata (limitação conhecida do esbuild), então a injeção implícita por
20
+ // tipo do Nest falha silenciosamente (reflector fica undefined em runtime,
21
+ // TypeError em qualquer rota guardada por ArgosGuard).
22
+ constructor(client, reflector) {
23
+ this.client = client;
24
+ this.reflector = reflector;
25
+ }
26
+ client;
27
+ reflector;
28
+ async canActivate(ctx) {
29
+ const meta = this.reflector.get(
30
+ OPERATION_KEY,
31
+ ctx.getHandler()
32
+ );
33
+ if (!meta) return true;
34
+ const { id, level, method } = meta;
35
+ const request = ctx.switchToHttp().getRequest();
36
+ if (level === "public") return true;
37
+ const auth = request.headers["authorization"] ?? "";
38
+ const [scheme, token] = auth.split(" ");
39
+ if (scheme?.toLowerCase() !== "bearer" || !token) {
40
+ throw new UnauthorizedException("Bearer token required.");
41
+ }
42
+ let claims;
43
+ try {
44
+ claims = await this.client.validateToken(token);
45
+ } catch {
46
+ throw new UnauthorizedException("Invalid token.");
47
+ }
48
+ request.argosUser = claims;
49
+ const allowed = this.client.checkPermission(claims, id, method);
50
+ if (!allowed) throw new ForbiddenException("Insufficient permissions.");
51
+ return true;
52
+ }
53
+ };
54
+ ArgosGuard = __decorateClass([
55
+ Injectable(),
56
+ __decorateParam(0, Inject(ArgosClient)),
57
+ __decorateParam(1, Inject(Reflector))
58
+ ], ArgosGuard);
59
+ var ArgosModule = class {
60
+ /**
61
+ * Register the argos module globally.
62
+ *
63
+ * Creates the `ArgosClient`, bootstraps it (authenticate + sync + fetch),
64
+ * and provides `ArgosGuard` for injection.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * // app.module.ts
69
+ * @Module({
70
+ * imports: [
71
+ * ArgosModule.forRootAsync({
72
+ * authorizerUrl: process.env.AUTHORIZER_URL!,
73
+ * realmId: process.env.REALM_ID!,
74
+ * appId: process.env.APP_ID!,
75
+ * secret: process.env.APP_SECRET!,
76
+ * }),
77
+ * ],
78
+ * })
79
+ * export class AppModule {}
80
+ * ```
81
+ */
82
+ static forRootAsync(options) {
83
+ return {
84
+ module: ArgosModule,
85
+ global: true,
86
+ providers: [
87
+ Reflector,
88
+ {
89
+ provide: ArgosClient,
90
+ useFactory: async () => {
91
+ const client = new ArgosClient(options);
92
+ for (const op of getRegistry()) client.registerOperation(op);
93
+ await client.startup();
94
+ return client;
95
+ }
96
+ },
97
+ ArgosGuard
98
+ ],
99
+ exports: [ArgosClient, ArgosGuard]
100
+ };
101
+ }
102
+ };
103
+ ArgosModule = __decorateClass([
104
+ Module({})
105
+ ], ArgosModule);
106
+
107
+ export { ArgosGuard, ArgosModule, ArgosUser, OPERATION_KEY, Operation };
108
+ //# sourceMappingURL=index.js.map
109
+ //# sourceMappingURL=index.js.map