@caronte-sdk/node 0.2.3 → 0.2.4
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 +49 -0
- package/dist/adapters/apollo.cjs +3 -0
- package/dist/adapters/apollo.cjs.map +1 -1
- package/dist/adapters/apollo.js +3 -0
- package/dist/adapters/apollo.js.map +1 -1
- package/dist/adapters/nest/index.cjs +12 -0
- package/dist/adapters/nest/index.cjs.map +1 -1
- package/dist/adapters/nest/index.d.cts +12 -0
- package/dist/adapters/nest/index.d.ts +12 -0
- package/dist/adapters/nest/index.js +12 -0
- package/dist/adapters/nest/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,6 +115,55 @@ export class TasksController {
|
|
|
115
115
|
}
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
#### Running with `otelCollectorUrl` on NestJS
|
|
119
|
+
|
|
120
|
+
`CaronteModule.forRootAsync()` alone is **not enough** to get request tracing
|
|
121
|
+
in a Nest app, even outside the ESM case above. `NestFactory.create()`
|
|
122
|
+
requires `express` (or `fastify`) internally to build the HTTP adapter
|
|
123
|
+
*before* any module's own providers — including `CaronteModule` — get a
|
|
124
|
+
chance to run. By the time `CaronteModule`'s factory calls `startup()` (and,
|
|
125
|
+
through it, `initOtel()`), the HTTP framework has already finished loading
|
|
126
|
+
unpatched, so auto-instrumentation never attaches to it. This is a Nest
|
|
127
|
+
bootstrap-ordering issue, distinct from the ESM loader-hook issue — it
|
|
128
|
+
affects CommonJS Nest apps too.
|
|
129
|
+
|
|
130
|
+
Fix: call `initOtel()` yourself, **before** `import { NestFactory } from
|
|
131
|
+
'@nestjs/core'`:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// main.ts
|
|
135
|
+
import 'reflect-metadata';
|
|
136
|
+
|
|
137
|
+
// Must run before @nestjs/core is required — see explanation above.
|
|
138
|
+
// CaronteModule still calls startup()/initOtel() too (harmless no-op,
|
|
139
|
+
// idempotent), so an app that skips this still gets traces/metrics/logs
|
|
140
|
+
// for everything except the HTTP layer itself.
|
|
141
|
+
import { initOtel } from '@caronte-sdk/node';
|
|
142
|
+
if (process.env.OTEL_COLLECTOR_URL) {
|
|
143
|
+
initOtel({
|
|
144
|
+
otelCollectorUrl: process.env.OTEL_COLLECTOR_URL,
|
|
145
|
+
appId: process.env.APP_ID!,
|
|
146
|
+
realmId: process.env.REALM_ID!,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
import { NestFactory } from '@nestjs/core';
|
|
151
|
+
import { AppModule } from './app.module';
|
|
152
|
+
|
|
153
|
+
async function bootstrap() {
|
|
154
|
+
const app = await NestFactory.create(AppModule);
|
|
155
|
+
await app.listen(3000);
|
|
156
|
+
}
|
|
157
|
+
bootstrap();
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This works because in CommonJS, `require()` calls run in the textual order
|
|
161
|
+
they appear — the same reason `reflect-metadata` is conventionally imported
|
|
162
|
+
first in this ecosystem. It only works if `main.ts` itself is CommonJS
|
|
163
|
+
(no `"type": "module"` in `package.json`, e.g. run via `ts-node`); an ESM
|
|
164
|
+
Nest app needs the `caronte-node` wrapper from the section above instead —
|
|
165
|
+
in that case skip this manual `initOtel()` call, the loader hook handles it.
|
|
166
|
+
|
|
118
167
|
### Apollo Server
|
|
119
168
|
|
|
120
169
|
```ts
|
package/dist/adapters/apollo.cjs
CHANGED
|
@@ -50,6 +50,9 @@ function carontePlugin(client) {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
const operationName = ctx.operationName ?? ctx.operation?.name?.value;
|
|
54
|
+
if (operationName) api.trace.getActiveSpan()?.setAttribute("graphql.operation.name", operationName);
|
|
55
|
+
if (ctx.operation?.operation) api.trace.getActiveSpan()?.setAttribute("graphql.operation.type", ctx.operation.operation);
|
|
53
56
|
}
|
|
54
57
|
};
|
|
55
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exceptions.ts","../../src/registry.ts","../../src/adapters/apollo.ts"],"names":["trace"],"mappings":";;;;;;;AAAO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,WAAA,CAAY,IAAA;AAAA,EAC/B;AACF,CAAA;AAGO,IAAM,iBAAA,GAAN,cAAkC,YAAA,CAAa;AAAC,CAAA;;;ACNvD,IAAM,YAAmC,EAAC;AAKnC,SAAS,aAAa,EAAA,EAAoB;AAC/C,EAAA,MAAM,IAAA,GAAA,CAAQ,GAAG,KAAA,CAAM,GAAG,EAAE,GAAA,EAAI,IAAK,IAAI,WAAA,EAAY;AACrD,EAAA,IAAI,wBAAA,CAAyB,IAAA,CAAK,IAAI,CAAA,EAAS,OAAO,MAAA;AACtD,EAAA,IAAI,0BAAA,CAA2B,IAAA,CAAK,IAAI,CAAA,EAAQ,OAAO,QAAA;AACvD,EAAA,IAAI,iCAAA,CAAkC,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,QAAA;AACzD,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,kBAAkB,EAAA,EAA+B;AAC/D,EAAA,MAAM,SAAS,SAAA,CAAU,IAAA;AAAA,IACvB,OAAK,CAAA,CAAE,UAAA,KAAe,GAAG,UAAA,IAAc,CAAA,CAAE,WAAW,EAAA,CAAG;AAAA,GACzD;AACA,EAAA,IAAI,CAAC,MAAA,EAAQ,SAAA,CAAU,IAAA,CAAK,EAAE,CAAA;AAChC;;;ACHO,SAAS,cAAc,MAAA,EAA2D;AACvF,EAAA,OAAO;AAAA,IACL,MAAM,eAAA,GAAkB;AACtB,MAAA,OAAO;AAAA,QACL,MAAM,oBAAoB,GAAA,EAA4C;AACpE,UAAA,MAAM,WAAY,GAAA,CAAI,OAAA,CAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA,IAAK,EAAA;AACpE,UAAA,MAAM,MAAA,GAAc,GAAA,CAAI,YAAA,EAAsB,gBAAA,EAAkB,aAAA,IAAwC,EAAA;AACxG,UAAA,MAAM,OAAY,QAAA,IAAY,MAAA;AAE9B,UAAA,MAAM,CAAC,MAAA,EAAQ,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AACtC,UAAA,IAAI,MAAA,EAAQ,WAAA,EAAY,KAAM,QAAA,IAAY,KAAA,EAAO;AAC/C,YAAA,IAAI;AACF,cAAA,GAAA,CAAI,YAAA,CAAa,WAAA,GAAc,MAAM,MAAA,CAAO,cAAc,KAAK,CAAA;AAC/D,cAAAA,SAAA,CAAM,eAAc,EAAG,YAAA,CAAa,gBAAgB,GAAA,CAAI,YAAA,CAAa,YAAY,GAAG,CAAA;AAAA,YACtF,SAAS,GAAA,EAAK;AACZ,cAAA,IAAI,eAAe,iBAAA,EAAmB;AACpC,gBAAA,GAAA,CAAI,aAAa,WAAA,GAAc,MAAA;AAAA,cACjC;AAAA,YACF;AAAA,UACF;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/exceptions.ts","../../src/registry.ts","../../src/adapters/apollo.ts"],"names":["trace"],"mappings":"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","file":"apollo.cjs","sourcesContent":["export class CaronteError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\nexport class CaronteAuthError extends CaronteError {}\nexport class CaronteTokenError extends CaronteError {}\nexport class CaronteForbiddenError extends CaronteError {}\nexport class CaronteSyncError extends CaronteError {}\nexport class CaronteConfigError extends CaronteError {}","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 type { ApolloServerPlugin, BaseContext, GraphQLRequestContext } from '@apollo/server';\nimport { trace } from '@opentelemetry/api';\nimport { CaronteClient } from '../client.js';\nimport { CaronteTokenError } from '../exceptions.js';\nimport type { TokenClaims } from '../models.js';\nimport { detectMethod, registerOperation } from '../registry.js';\n\nexport interface CaronteContext extends BaseContext {\n caronteUser?: TokenClaims;\n}\n\n/**\n * Apollo Server plugin for caronte.\n *\n * Validates the Bearer token on every request and stores the claims in\n * `context.caronteUser`. Use `createGuard(client)` to enforce per-resolver\n * permissions.\n */\nexport function carontePlugin(client: CaronteClient): ApolloServerPlugin<CaronteContext> {\n return {\n async requestDidStart() {\n return {\n async didResolveOperation(ctx: GraphQLRequestContext<CaronteContext>) {\n const httpAuth = ctx.request.http?.headers.get('authorization') ?? '';\n const wsAuth = ((ctx.contextValue as any)?.connectionParams?.Authorization as string | undefined) ?? '';\n const auth = httpAuth || wsAuth;\n\n const [scheme, token] = auth.split(' ');\n if (scheme?.toLowerCase() === 'bearer' && token) {\n try {\n ctx.contextValue.caronteUser = await client.validateToken(token);\n trace.getActiveSpan()?.setAttribute('caronte.user', ctx.contextValue.caronteUser.sub);\n } catch (err) {\n if (err instanceof CaronteTokenError) {\n ctx.contextValue.caronteUser = undefined;\n }\n }\n }\n\n // Sem isso, toda requisição GraphQL aparece nas listas de trace\n // como \"POST /graphql\" genérico -- o nome/tipo da operação\n // (query/mutation) só existe aqui dentro do Apollo, nunca chega\n // no span HTTP. O span ativo neste ponto é o span do middleware\n // Express que envolve o handler do Apollo (não o span raiz\n // \"POST /graphql\" -- instrumentation-express cria um span por\n // camada de middleware, todos filhos diretos do span raiz), então\n // o backend precisa pedir mais spans por trace (spss) pra achar\n // esse atributo -- ver tempo.module.ts.\n const operationName = ctx.operationName ?? ctx.operation?.name?.value;\n if (operationName) trace.getActiveSpan()?.setAttribute('graphql.operation.name', operationName);\n if (ctx.operation?.operation) trace.getActiveSpan()?.setAttribute('graphql.operation.type', ctx.operation.operation);\n },\n };\n },\n };\n}\n\n/**\n * Factory that returns a per-resolver guard bound to a `CaronteClient`.\n *\n * @example\n * ```ts\n * const guard = createGuard(client);\n *\n * const resolvers = {\n * Query: {\n * tasks: guard('tasks:list', 'private', async (_parent, _args, context) => {\n * const user = context.caronteUser;\n * return db.tasks.findAll();\n * }),\n * },\n * };\n * ```\n */\nexport function createGuard(client: CaronteClient) {\n return function guard<TParent, TArgs, TContext extends CaronteContext, TReturn>(\n id: string,\n level: string,\n resolver: (parent: TParent, args: TArgs, context: TContext, info: unknown) => TReturn,\n method?: string,\n ): (parent: TParent, args: TArgs, context: TContext, info: unknown) => TReturn {\n const resolvedMethod = method ?? detectMethod(id);\n registerOperation({ identifier: id, method: resolvedMethod, level });\n\n return (parent, args, context, info) => {\n const span = trace.getActiveSpan();\n span?.setAttribute('caronte.operation_id', id);\n\n if (level === 'public') {\n span?.setAttribute('caronte.permission_result', 'public');\n return resolver(parent, args, context, info);\n }\n if (!context.caronteUser) {\n span?.setAttribute('caronte.permission_result', 'unauthorized');\n throw new Error('Unauthorized: Bearer token required.');\n }\n const allowed = client.checkPermission(context.caronteUser, id, resolvedMethod);\n span?.setAttribute('caronte.permission_result', allowed ? 'allowed' : 'forbidden');\n if (!allowed) {\n throw new Error('Forbidden: Insufficient permissions.');\n }\n return resolver(parent, args, context, info);\n };\n };\n}"]}
|
package/dist/adapters/apollo.js
CHANGED
|
@@ -21,6 +21,9 @@ function carontePlugin(client) {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
const operationName = ctx.operationName ?? ctx.operation?.name?.value;
|
|
25
|
+
if (operationName) trace.getActiveSpan()?.setAttribute("graphql.operation.name", operationName);
|
|
26
|
+
if (ctx.operation?.operation) trace.getActiveSpan()?.setAttribute("graphql.operation.type", ctx.operation.operation);
|
|
24
27
|
}
|
|
25
28
|
};
|
|
26
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/apollo.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,cAAc,MAAA,EAA2D;AACvF,EAAA,OAAO;AAAA,IACL,MAAM,eAAA,GAAkB;AACtB,MAAA,OAAO;AAAA,QACL,MAAM,oBAAoB,GAAA,EAA4C;AACpE,UAAA,MAAM,WAAY,GAAA,CAAI,OAAA,CAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA,IAAK,EAAA;AACpE,UAAA,MAAM,MAAA,GAAc,GAAA,CAAI,YAAA,EAAsB,gBAAA,EAAkB,aAAA,IAAwC,EAAA;AACxG,UAAA,MAAM,OAAY,QAAA,IAAY,MAAA;AAE9B,UAAA,MAAM,CAAC,MAAA,EAAQ,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AACtC,UAAA,IAAI,MAAA,EAAQ,WAAA,EAAY,KAAM,QAAA,IAAY,KAAA,EAAO;AAC/C,YAAA,IAAI;AACF,cAAA,GAAA,CAAI,YAAA,CAAa,WAAA,GAAc,MAAM,MAAA,CAAO,cAAc,KAAK,CAAA;AAC/D,cAAA,KAAA,CAAM,eAAc,EAAG,YAAA,CAAa,gBAAgB,GAAA,CAAI,YAAA,CAAa,YAAY,GAAG,CAAA;AAAA,YACtF,SAAS,GAAA,EAAK;AACZ,cAAA,IAAI,eAAe,iBAAA,EAAmB;AACpC,gBAAA,GAAA,CAAI,aAAa,WAAA,GAAc,MAAA;AAAA,cACjC;AAAA,YACF;AAAA,UACF;AAAA,
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/apollo.ts"],"names":[],"mappings":"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","file":"apollo.js","sourcesContent":["import type { ApolloServerPlugin, BaseContext, GraphQLRequestContext } from '@apollo/server';\nimport { trace } from '@opentelemetry/api';\nimport { CaronteClient } from '../client.js';\nimport { CaronteTokenError } from '../exceptions.js';\nimport type { TokenClaims } from '../models.js';\nimport { detectMethod, registerOperation } from '../registry.js';\n\nexport interface CaronteContext extends BaseContext {\n caronteUser?: TokenClaims;\n}\n\n/**\n * Apollo Server plugin for caronte.\n *\n * Validates the Bearer token on every request and stores the claims in\n * `context.caronteUser`. Use `createGuard(client)` to enforce per-resolver\n * permissions.\n */\nexport function carontePlugin(client: CaronteClient): ApolloServerPlugin<CaronteContext> {\n return {\n async requestDidStart() {\n return {\n async didResolveOperation(ctx: GraphQLRequestContext<CaronteContext>) {\n const httpAuth = ctx.request.http?.headers.get('authorization') ?? '';\n const wsAuth = ((ctx.contextValue as any)?.connectionParams?.Authorization as string | undefined) ?? '';\n const auth = httpAuth || wsAuth;\n\n const [scheme, token] = auth.split(' ');\n if (scheme?.toLowerCase() === 'bearer' && token) {\n try {\n ctx.contextValue.caronteUser = await client.validateToken(token);\n trace.getActiveSpan()?.setAttribute('caronte.user', ctx.contextValue.caronteUser.sub);\n } catch (err) {\n if (err instanceof CaronteTokenError) {\n ctx.contextValue.caronteUser = undefined;\n }\n }\n }\n\n // Sem isso, toda requisição GraphQL aparece nas listas de trace\n // como \"POST /graphql\" genérico -- o nome/tipo da operação\n // (query/mutation) só existe aqui dentro do Apollo, nunca chega\n // no span HTTP. O span ativo neste ponto é o span do middleware\n // Express que envolve o handler do Apollo (não o span raiz\n // \"POST /graphql\" -- instrumentation-express cria um span por\n // camada de middleware, todos filhos diretos do span raiz), então\n // o backend precisa pedir mais spans por trace (spss) pra achar\n // esse atributo -- ver tempo.module.ts.\n const operationName = ctx.operationName ?? ctx.operation?.name?.value;\n if (operationName) trace.getActiveSpan()?.setAttribute('graphql.operation.name', operationName);\n if (ctx.operation?.operation) trace.getActiveSpan()?.setAttribute('graphql.operation.type', ctx.operation.operation);\n },\n };\n },\n };\n}\n\n/**\n * Factory that returns a per-resolver guard bound to a `CaronteClient`.\n *\n * @example\n * ```ts\n * const guard = createGuard(client);\n *\n * const resolvers = {\n * Query: {\n * tasks: guard('tasks:list', 'private', async (_parent, _args, context) => {\n * const user = context.caronteUser;\n * return db.tasks.findAll();\n * }),\n * },\n * };\n * ```\n */\nexport function createGuard(client: CaronteClient) {\n return function guard<TParent, TArgs, TContext extends CaronteContext, TReturn>(\n id: string,\n level: string,\n resolver: (parent: TParent, args: TArgs, context: TContext, info: unknown) => TReturn,\n method?: string,\n ): (parent: TParent, args: TArgs, context: TContext, info: unknown) => TReturn {\n const resolvedMethod = method ?? detectMethod(id);\n registerOperation({ identifier: id, method: resolvedMethod, level });\n\n return (parent, args, context, info) => {\n const span = trace.getActiveSpan();\n span?.setAttribute('caronte.operation_id', id);\n\n if (level === 'public') {\n span?.setAttribute('caronte.permission_result', 'public');\n return resolver(parent, args, context, info);\n }\n if (!context.caronteUser) {\n span?.setAttribute('caronte.permission_result', 'unauthorized');\n throw new Error('Unauthorized: Bearer token required.');\n }\n const allowed = client.checkPermission(context.caronteUser, id, resolvedMethod);\n span?.setAttribute('caronte.permission_result', allowed ? 'allowed' : 'forbidden');\n if (!allowed) {\n throw new Error('Forbidden: Insufficient permissions.');\n }\n return resolver(parent, args, context, info);\n };\n };\n}"]}
|
|
@@ -323,6 +323,18 @@ exports.CaronteModule = class CaronteModule {
|
|
|
323
323
|
* })
|
|
324
324
|
* export class AppModule {}
|
|
325
325
|
* ```
|
|
326
|
+
*
|
|
327
|
+
* @remarks
|
|
328
|
+
* If `options.otelCollectorUrl` is set, this alone does **not** get you
|
|
329
|
+
* request tracing: `NestFactory.create()` requires express/fastify
|
|
330
|
+
* internally to build the HTTP adapter *before* this module's provider
|
|
331
|
+
* factory (and its `startup()`/`initOtel()` call) ever runs, so
|
|
332
|
+
* auto-instrumentation attaches too late. Call `initOtel()` from
|
|
333
|
+
* `@caronte-sdk/node` yourself, before `import { NestFactory } from
|
|
334
|
+
* '@nestjs/core'` in `main.ts` (CommonJS only — `require()` order is
|
|
335
|
+
* preserved textually there). See the README's "Running with
|
|
336
|
+
* otelCollectorUrl on NestJS" section for the full example. The call
|
|
337
|
+
* this module makes is a harmless idempotent no-op either way.
|
|
326
338
|
*/
|
|
327
339
|
static forRootAsync(options) {
|
|
328
340
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/registry.ts","../../../src/adapters/nest/decorator.ts","../../../src/exceptions.ts","../../../src/otel.ts","../../../src/client.ts","../../../src/adapters/nest/guard.ts","../../../src/adapters/nest/module.ts"],"names":["SetMetadata","createParamDecorator","defaultResource","resourceFromAttributes","ATTR_SERVICE_NAME","ATTR_SERVICE_NAMESPACE","NodeSDK","OTLPTraceExporter","PeriodicExportingMetricReader","OTLPMetricExporter","BatchLogRecordProcessor","OTLPLogExporter","getNodeAutoInstrumentations","logs","SeverityNumber","createRemoteJWKSet","jwtVerify","CaronteGuard","trace","UnauthorizedException","ForbiddenException","Injectable","Reflector","CaronteModule","Module"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAM,YAAmC,EAAC;AAKnC,SAAS,aAAa,EAAA,EAAoB;AAC/C,EAAA,MAAM,IAAA,GAAA,CAAQ,GAAG,KAAA,CAAM,GAAG,EAAE,GAAA,EAAI,IAAK,IAAI,WAAA,EAAY;AACrD,EAAA,IAAI,wBAAA,CAAyB,IAAA,CAAK,IAAI,CAAA,EAAS,OAAO,MAAA;AACtD,EAAA,IAAI,0BAAA,CAA2B,IAAA,CAAK,IAAI,CAAA,EAAQ,OAAO,QAAA;AACvD,EAAA,IAAI,iCAAA,CAAkC,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,QAAA;AACzD,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,kBAAkB,EAAA,EAA+B;AAC/D,EAAA,MAAM,SAAS,SAAA,CAAU,IAAA;AAAA,IACvB,OAAK,CAAA,CAAE,UAAA,KAAe,GAAG,UAAA,IAAc,CAAA,CAAE,WAAW,EAAA,CAAG;AAAA,GACzD;AACA,EAAA,IAAI,CAAC,MAAA,EAAQ,SAAA,CAAU,IAAA,CAAK,EAAE,CAAA;AAChC;AAEO,SAAS,WAAA,GAAqC;AACnD,EAAA,OAAO,CAAC,GAAG,SAAS,CAAA;AACtB;;;ACrBO,IAAM,aAAA,GAAgB;AAkBtB,SAAS,SAAA,CAAU,EAAA,EAAY,KAAA,EAAe,MAAA,EAAkC;AACrF,EAAA,MAAM,cAAA,GAAiB,MAAA,IAAU,YAAA,CAAa,EAAE,CAAA;AAChD,EAAA,iBAAA,CAAkB,EAAE,UAAA,EAAY,EAAA,EAAI,MAAA,EAAQ,cAAA,EAAgB,OAAO,CAAA;AACnE,EAAA,OAAOA,mBAAmC,aAAA,EAAe,EAAE,IAAI,KAAA,EAAO,MAAA,EAAQ,gBAAgB,CAAA;AAChG;AAGO,IAAM,WAAA,GAAcC,2BAAA;AAAA,EACzB,CAAC,KAAA,EAAgB,GAAA,KACf,IAAI,YAAA,EAAa,CAAE,YAAW,CAAE;AACpC;;;AChCO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,WAAA,CAAY,IAAA;AAAA,EAC/B;AACF,CAAA;AAEO,IAAM,gBAAA,GAAN,cAAkC,YAAA,CAAa;AAAC,CAAA;AAChD,IAAM,iBAAA,GAAN,cAAkC,YAAA,CAAa;AAAC,CAAA;AAEhD,IAAM,gBAAA,GAAN,cAAkC,YAAA,CAAa;AAAC,CAAA;AAChD,IAAM,kBAAA,GAAN,cAAkC,YAAA,CAAa;AAAC,CAAA;ACMvD,IAAI,OAAA,GAAU,KAAA;AASP,SAAS,SAAS,OAAA,EAAgC;AACvD,EAAA,IAAI,OAAA,EAAS;AACb,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,gBAAA,CAAiB,OAAA,CAAQ,OAAO,EAAE,CAAA;AACvD,IAAA,MAAM,QAAA,GAAWC,yBAAA,EAAgB,CAAE,KAAA,CAAMC,gCAAA,CAAuB;AAAA,MAC9D,CAACC,qCAAiB,GAAG,OAAA,CAAQ,KAAA;AAAA,MAC7B,CAACC,0CAAsB,GAAG,OAAA,CAAQ;AAAA,KACnC,CAAC,CAAA;AAEF,IAAA,MAAM,GAAA,GAAM,IAAIC,eAAA,CAAQ;AAAA,MACtB,QAAA;AAAA,MACA,aAAA,EAAe,IAAIC,uCAAA,CAAkB,EAAE,KAAK,CAAA,EAAG,IAAI,cAAc,CAAA;AAAA,MACjE,aAAA,EAAe;AAAA,QACb,IAAIC,wCAAA,CAA8B;AAAA,UAChC,QAAA,EAAU,IAAIC,0CAAA,CAAmB,EAAE,KAAK,CAAA,EAAG,IAAI,eAAe;AAAA,SAC/D;AAAA,OACH;AAAA,MACA,mBAAA,EAAqB;AAAA,QACnB,IAAIC,+BAAA,CAAwB,EAAE,QAAA,EAAU,IAAIC,oCAAA,CAAgB,EAAE,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,QAAA,CAAA,EAAY,GAAG;AAAA,OAC3F;AAAA,MACA,gBAAA,EAAkB,CAACC,oDAAA,EAA6B;AAAA,KACjD,CAAA;AACD,IAAA,GAAA,CAAI,KAAA,EAAM;AACV,IAAA,OAAA,GAAU,IAAA;AAMV,IAAAC,YAAA,CAAK,SAAA,CAAU,aAAa,CAAA,CAAE,IAAA,CAAK;AAAA,MACjC,gBAAgBC,sBAAA,CAAe,IAAA;AAAA,MAC/B,MAAM,CAAA,wCAAA,EAA2C,OAAA,CAAQ,KAAK,CAAA,UAAA,EAAa,QAAQ,OAAO,CAAA;AAAA,KAC3F,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,2CAAA,EAA+C,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,EACrF;AACF;;;AC5CO,IAAM,aAAA,GAAN,MAAM,cAAA,CAAc;AAAA,EACR,IAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,gBAAA;AAAA,EAET,QAAA,GAA0B,IAAA;AAAA,EAC1B,IAAA,GAAqD,IAAA;AAAA,EACrD,aAAoC,EAAC;AAAA,EACrC,uBAA8C,EAAC;AAAA,EAEvD,YAAY,OAAA,EAA+B;AACzC,IAAA,IAAA,CAAK,IAAA,GAAW,OAAA,CAAQ,aAAA,CAAc,OAAA,CAAQ,OAAO,EAAE,CAAA;AACvD,IAAA,IAAA,CAAK,UAAW,OAAA,CAAQ,OAAA;AACxB,IAAA,IAAA,CAAK,QAAW,OAAA,CAAQ,KAAA;AACxB,IAAA,IAAA,CAAK,SAAW,OAAA,CAAQ,MAAA;AACxB,IAAA,IAAA,CAAK,mBAAmB,OAAA,CAAQ,gBAAA;AAAA,EAClC;AAAA,EAEA,IAAY,SAAA,GAAoB;AAC9B,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,QAAA,EAAW,KAAK,OAAO,CAAA,CAAA;AAAA,EAC5C;AAAA,EAEA,kBAAkB,EAAA,EAA+B;AAC/C,IAAA,IAAA,CAAK,oBAAA,CAAqB,KAAK,EAAE,CAAA;AAAA,EACnC;AAAA,EAEA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,oBAAA,CAAqB,MAAA,KAAW,CAAA,EAAG;AAC1C,MAAA,MAAM,IAAI,kBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,KAAK,gBAAA,EAAkB;AACzB,MAAA,QAAA,CAAS,EAAE,gBAAA,EAAkB,IAAA,CAAK,gBAAA,EAAkB,KAAA,EAAO,KAAK,KAAA,EAAO,OAAA,EAAS,IAAA,CAAK,OAAA,EAAS,CAAA;AAAA,IAChG;AACA,IAAA,MAAM,KAAK,YAAA,EAAa;AACxB,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,MAAM,KAAK,eAAA,EAAgB;AAAA,EAC7B;AAAA,EAEA,MAAM,YAAA,GAA8B;AAClC,IAAA,MAAM,MAAM,MAAM,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,SAAS,CAAA,WAAA,CAAA,EAAe;AAAA,MACtD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,MAAA,EAAQ,KAAK,KAAA,EAAO,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ;AAAA,KACjE,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,gBAAA;AAAA,QACR,+BAA+B,GAAA,CAAI,MAAM,WAAM,MAAM,GAAA,CAAI,MAAM,CAAA;AAAA,OACjE;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,CAAC,IAAA,CAAK,YAAA,EAAc,MAAM,IAAI,iBAAiB,sCAAsC,CAAA;AACzF,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,YAAA;AAAA,EACvB;AAAA,EAEQ,QAAA,GAAiB;AACvB,IAAA,IAAA,CAAK,IAAA,GAAOC,uBAAA;AAAA,MACV,IAAI,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,SAAS,CAAA,8BAAA,CAAgC;AAAA,KAC3D;AAAA,EACF;AAAA,EAEA,MAAM,cAAA,GAAgC;AACpC,IAAA,IAAA,CAAK,cAAA,EAAe;AACpB,IAAA,MAAM,MAAM,MAAM,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,SAAS,CAAA,qBAAA,CAAA,EAAyB;AAAA,MAChE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,QAAQ,CAAA;AAAA,OACxC;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,UAAA,EAAY,IAAA,CAAK,oBAAA,CAAqB,GAAA,CAAI,CAAA,EAAA,MAAO;AAAA,UAC/C,YAAa,EAAA,CAAG,UAAA;AAAA,UAChB,QAAa,EAAA,CAAG,MAAA;AAAA,UAChB,OAAa,EAAA,CAAG,KAAA;AAAA,UAChB,WAAA,EAAa,GAAG,WAAA,IAAe;AAAA,SACjC,CAAE;AAAA,OACH;AAAA,KACF,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,gBAAA,CAAiB,CAAA,kBAAA,EAAqB,GAAA,CAAI,MAAM,WAAM,MAAM,GAAA,CAAI,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IACpF;AAAA,EACF;AAAA,EAEA,MAAM,eAAA,GAAiC;AACrC,IAAA,IAAA,CAAK,cAAA,EAAe;AACpB,IAAA,MAAM,MAAM,MAAM,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,SAAS,CAAA,gBAAA,CAAA,EAAoB;AAAA,MAC3D,SAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,QAAQ,CAAA,CAAA;AAAG,KACrD,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,MAAM,IAAI,YAAA;AAAA,QACR,iCAAiC,GAAA,CAAI,MAAM,WAAM,MAAM,GAAA,CAAI,MAAM,CAAA;AAAA,OACnE;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,CAAA,EAAA,MAAO;AAAA,MAC3C,aAAe,EAAA,CAAG,YAAA;AAAA,MAClB,YAAe,EAAA,CAAG,UAAA;AAAA,MAClB,QAAe,EAAA,CAAG,MAAA;AAAA,MAClB,OAAe,EAAA,CAAG,KAAA;AAAA,MAClB,aAAA,EAAe,EAAA,CAAG,cAAA,IAAkB;AAAC,KACvC,CAAE,CAAA;AAAA,EACJ;AAAA,EAEA,MAAM,cAAc,KAAA,EAAqC;AACvD,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,QAAA,EAAS;AAC9B,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,MAAMC,cAAA,CAAU,KAAA,EAAO,KAAK,IAAK,CAAA;AACrD,MAAA,MAAM,CAAA,GAAI,OAAA;AACV,MAAA,MAAM,UAAA,GAAc,CAAA,CAAE,UAAU,CAAA,IAAgB,EAAA;AAOhD,MAAA,IAAI,WAAW,WAAA,EAAY,KAAM,IAAA,CAAK,OAAA,CAAQ,aAAY,EAAG;AAC3D,QAAA,MAAM,IAAI,iBAAA;AAAA,UACR,CAAA,aAAA,EAAgB,UAAU,CAAA,mCAAA,EAAsC,IAAA,CAAK,OAAO,CAAA,EAAA;AAAA,SAC9E;AAAA,MACF;AAEA,MAAA,OAAO;AAAA,QACL,GAAA,EAAS,QAAQ,GAAA,IAAO,EAAA;AAAA,QACxB,OAAA,EAAS,UAAA;AAAA,QACT,MAAA,EAAU,CAAA,CAAE,QAAQ,CAAA,IAAkB,EAAC;AAAA,QACvC,GAAA,EAAS,QAAQ,GAAA,IAAO,CAAA;AAAA,QACxB,GAAA,EAAS;AAAA,OACX;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,GAAA,YAAe,mBAAmB,MAAM,GAAA;AAC5C,MAAA,MAAM,IAAI,iBAAA,CAAkB,CAAA,eAAA,EAAmB,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,eAAA,CAAgB,MAAA,EAAqB,UAAA,EAAoB,MAAA,EAAyB;AAChF,IAAA,MAAM,EAAA,GAAK,KAAK,UAAA,CAAW,IAAA;AAAA,MACzB,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,KAAe,UAAA,IAAc,EAAE,MAAA,KAAW;AAAA,KACnD;AACA,IAAA,IAAI,CAAC,IAAI,OAAO,KAAA;AAChB,IAAA,IAAI,EAAA,CAAG,KAAA,KAAU,QAAA,EAAa,OAAO,IAAA;AACrC,IAAA,IAAI,GAAG,KAAA,KAAU,SAAA,EAAa,OAAO,MAAA,CAAO,OAAO,MAAA,GAAS,CAAA;AAC5D,IAAA,IAAI,EAAA,CAAG,KAAA,KAAU,WAAA,EAAa,OAAO,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,CAAA,CAAA,KAAK,EAAA,CAAG,aAAA,CAAc,QAAA,CAAS,CAAC,CAAC,CAAA;AACzF,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,OAAO,OAAA,EAAuD;AACzE,IAAA,MAAM,MAAA,GAAS,IAAI,cAAA,CAAc,OAAO,CAAA;AACxC,IAAA,KAAA,MAAW,EAAA,IAAM,WAAA,EAAY,EAAG,MAAA,CAAO,kBAAkB,EAAE,CAAA;AAC3D,IAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,MAAM,IAAI,iBAAiB,uDAAuD,CAAA;AAAA,IACpF;AAAA,EACF;AACF,CAAA;;;ACzKaC,uBAAN,kBAAA,CAA0C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/C,WAAA,CAC0C,QACJ,SAAA,EACpC;AAFwC,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACJ,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAAA,EACnC;AAAA,EAFuC,MAAA;AAAA,EACJ,SAAA;AAAA,EAGtC,MAAM,YAAY,GAAA,EAAyC;AACzD,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU,GAAA;AAAA,MAC1B,aAAA;AAAA,MACA,IAAI,UAAA;AAAW,KACjB;AAEA,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,IAAA,MAAM,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAO,GAAI,IAAA;AAC9B,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,YAAA,EAAa,CAAE,UAAA,EAA2E;AAC9G,IAAA,MAAM,IAAA,GAAOC,UAAM,aAAA,EAAc;AACjC,IAAA,IAAA,EAAM,YAAA,CAAa,wBAAwB,EAAE,CAAA;AAE7C,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,IAAA,EAAM,YAAA,CAAa,6BAA6B,QAAQ,CAAA;AACxD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,CAAQ,eAAe,CAAA,IAAK,EAAA;AACjD,IAAA,MAAM,CAAC,MAAA,EAAQ,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,GAAG,CAAA;AAEtC,IAAA,IAAI,MAAA,EAAQ,WAAA,EAAY,KAAM,QAAA,IAAY,CAAC,KAAA,EAAO;AAChD,MAAA,IAAA,EAAM,YAAA,CAAa,6BAA6B,cAAc,CAAA;AAC9D,MAAA,MAAM,IAAIC,6BAAsB,wBAAwB,CAAA;AAAA,IAC1D;AAEA,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,KAAK,CAAA;AAAA,IAChD,CAAA,CAAA,MAAQ;AAIN,MAAA,IAAA,EAAM,YAAA,CAAa,6BAA6B,cAAc,CAAA;AAC9D,MAAA,MAAM,IAAIA,6BAAsB,gBAAgB,CAAA;AAAA,IAClD;AACA,IAAA,OAAA,CAAQ,WAAA,GAAc,MAAA;AACtB,IAAA,IAAA,EAAM,YAAA,CAAa,cAAA,EAAgB,MAAA,CAAO,GAAG,CAAA;AAE7C,IAAA,MAAM,UAAU,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,MAAA,EAAQ,IAAI,MAAM,CAAA;AAC9D,IAAA,IAAA,EAAM,YAAA,CAAa,2BAAA,EAA6B,OAAA,GAAU,SAAA,GAAY,WAAW,CAAA;AACjF,IAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAIC,0BAAmB,2BAA2B,CAAA;AAEtE,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAxDaH,oBAAA,GAAN,eAAA,CAAA;AAAA,EADNI,iBAAA,EAAW;AAAA,EAQP,iCAAO,aAAa,CAAA,CAAA;AAAA,EACpB,iCAAOC,cAAS,CAAA;AAAA,CAAA,EARRL,oBAAA,CAAA;ACFAM,wBAAN,mBAAA,CAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBzB,OAAO,aAAa,OAAA,EAA8C;AAChE,IAAA,OAAO;AAAA,MACL,MAAA,EAAQA,qBAAA;AAAA,MACR,MAAA,EAAQ,IAAA;AAAA,MACR,SAAA,EAAW;AAAA,QACTD,cAAAA;AAAA,QACA;AAAA,UACE,OAAA,EAAS,aAAA;AAAA,UACT,YAAY,YAAY;AACtB,YAAA,MAAM,MAAA,GAAS,IAAI,aAAA,CAAc,OAAO,CAAA;AACxC,YAAA,KAAA,MAAW,EAAA,IAAM,WAAA,EAAY,EAAG,MAAA,CAAO,kBAAkB,EAAE,CAAA;AAC3D,YAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,YAAA,OAAO,MAAA;AAAA,UACT;AAAA,SACF;AAAA,QACAL;AAAA,OACF;AAAA,MACA,OAAA,EAAS,CAAC,aAAA,EAAeA,oBAAY;AAAA,KACvC;AAAA,EACF;AACF;AA3CaM,qBAAA,GAAN,eAAA,CAAA;AAAA,EADNC,aAAA,CAAO,EAAE;AAAA,CAAA,EACGD,qBAAA,CAAA","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 = 'caronte:operation';\n\nexport interface OperationMeta {\n id: string;\n level: string;\n method: string;\n}\n\n/**\n * Marks a controller method as a caronte operation.\n *\n * @example\n * ```ts\n * @Get()\n * @Operation('tasks:list', 'private')\n * listTasks(@CaronteUser() 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 CaronteUser = createParamDecorator(\n (_data: unknown, ctx: ExecutionContext): TokenClaims | undefined =>\n ctx.switchToHttp().getRequest().caronteUser,\n);","export class CaronteError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\nexport class CaronteAuthError extends CaronteError {}\nexport class CaronteTokenError extends CaronteError {}\nexport class CaronteForbiddenError extends CaronteError {}\nexport class CaronteSyncError extends CaronteError {}\nexport class CaronteConfigError extends CaronteError {}","import { NodeSDK } from '@opentelemetry/sdk-node';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';\nimport { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\nimport { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';\nimport { ATTR_SERVICE_NAME, ATTR_SERVICE_NAMESPACE } from '@opentelemetry/semantic-conventions';\nimport { logs, SeverityNumber } from '@opentelemetry/api-logs';\n\nexport interface OtelInitOptions {\n otelCollectorUrl: string;\n appId: string;\n realmId: string;\n}\n\nlet started = false;\n\n/**\n * Best-effort OTel bootstrap: a misconfigured or unreachable collector must\n * never break CaronteClient.startup() (auth/JWKS still have to work), so\n * every failure here is swallowed. Guarded by `started` because NodeSDK is a\n * process-wide singleton — re-running .start() would double-register the\n * auto-instrumentations' require hooks.\n */\nexport function initOtel(options: OtelInitOptions): void {\n if (started) return;\n try {\n const base = options.otelCollectorUrl.replace(/\\/$/, '');\n const resource = defaultResource().merge(resourceFromAttributes({\n [ATTR_SERVICE_NAME]: options.appId,\n [ATTR_SERVICE_NAMESPACE]: options.realmId,\n }));\n\n const sdk = new NodeSDK({\n resource,\n traceExporter: new OTLPTraceExporter({ url: `${base}/v1/traces` }),\n metricReaders: [\n new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({ url: `${base}/v1/metrics` }),\n }),\n ],\n logRecordProcessors: [\n new BatchLogRecordProcessor({ exporter: new OTLPLogExporter({ url: `${base}/v1/logs` }) }),\n ],\n instrumentations: [getNodeAutoInstrumentations()],\n });\n sdk.start();\n started = true;\n\n // Auto-instrumentation only yields traces (and, from real HTTP traffic,\n // metrics) — nothing captures console output as OTel logs. Emit one\n // bootstrap record so the log pipeline (client -> Collector -> Loki) is\n // provably wired even before the app receives its first request.\n logs.getLogger('caronte-sdk').emit({\n severityNumber: SeverityNumber.INFO,\n body: `caronte-sdk OTel initialized for app_id=${options.appId} realm_id=${options.realmId}`,\n });\n } catch (err) {\n console.warn(`[caronte-sdk] OTel initialization skipped: ${(err as Error).message}`);\n }\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport {\n CaronteAuthError, CaronteConfigError, CaronteError,\n CaronteSyncError, CaronteTokenError,\n} from './exceptions.js';\nimport type { OperationDescriptor, OperationWithGroups, TokenClaims } from './models.js';\nimport { initOtel } from './otel.js';\nimport { getRegistry } from './registry.js';\n\nexport interface CaronteClientOptions {\n authorizerUrl: string;\n realmId: string;\n appId: string;\n secret: string;\n /** Opt-in: URL of an OTLP collector (e.g. http://localhost:4318). Omit to skip OTel entirely. */\n otelCollectorUrl?: string;\n}\n\nexport class CaronteClient {\n private readonly base: string;\n private readonly realmId: string;\n private readonly appId: string;\n private readonly secret: string;\n private readonly otelCollectorUrl?: 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: CaronteClientOptions) {\n this.base = options.authorizerUrl.replace(/\\/$/, '');\n this.realmId = options.realmId;\n this.appId = options.appId;\n this.secret = options.secret;\n this.otelCollectorUrl = options.otelCollectorUrl;\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 CaronteConfigError(\n 'No operations registered. Call registerOperation() before startup().',\n );\n }\n if (this.otelCollectorUrl) {\n initOtel({ otelCollectorUrl: this.otelCollectorUrl, appId: this.appId, realmId: this.realmId });\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 CaronteAuthError(\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 CaronteAuthError('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 CaronteSyncError(`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 CaronteError(\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 CaronteTokenError(\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 CaronteTokenError) throw err;\n throw new CaronteTokenError(`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: CaronteClientOptions): Promise<CaronteClient> {\n const client = new CaronteClient(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 CaronteAuthError('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 { trace } from '@opentelemetry/api';\nimport { CaronteClient } from '../../client.js';\nimport type { TokenClaims } from '../../models.js';\nimport { OPERATION_KEY, type OperationMeta } from './decorator.js';\n\n@Injectable()\nexport class CaronteGuard 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 CaronteGuard).\n constructor(\n @Inject(CaronteClient) private readonly client: CaronteClient,\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>; caronteUser?: TokenClaims }>();\n const span = trace.getActiveSpan();\n span?.setAttribute('caronte.operation_id', id);\n\n if (level === 'public') {\n span?.setAttribute('caronte.permission_result', 'public');\n return true;\n }\n\n const auth = request.headers['authorization'] ?? '';\n const [scheme, token] = auth.split(' ');\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n span?.setAttribute('caronte.permission_result', 'unauthorized');\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 span?.setAttribute('caronte.permission_result', 'unauthorized');\n throw new UnauthorizedException('Invalid token.');\n }\n request.caronteUser = claims;\n span?.setAttribute('caronte.user', claims.sub);\n\n const allowed = this.client.checkPermission(claims, id, method);\n span?.setAttribute('caronte.permission_result', allowed ? 'allowed' : 'forbidden');\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 { CaronteClient, type CaronteClientOptions } from '../../client.js';\nimport { getRegistry } from '../../registry.js';\nimport { CaronteGuard } from './guard.js';\n\nexport interface CaronteModuleOptions extends CaronteClientOptions {}\n\n@Module({})\nexport class CaronteModule {\n /**\n * Register the caronte module globally.\n *\n * Creates the `CaronteClient`, bootstraps it (authenticate + sync + fetch),\n * and provides `CaronteGuard` for injection.\n *\n * @example\n * ```ts\n * // app.module.ts\n * @Module({\n * imports: [\n * CaronteModule.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: CaronteModuleOptions): DynamicModule {\n return {\n module: CaronteModule,\n global: true,\n providers: [\n Reflector,\n {\n provide: CaronteClient,\n useFactory: async () => {\n const client = new CaronteClient(options);\n for (const op of getRegistry()) client.registerOperation(op);\n await client.startup();\n return client;\n },\n },\n CaronteGuard,\n ],\n exports: [CaronteClient, CaronteGuard],\n };\n }\n}"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/registry.ts","../../../src/adapters/nest/decorator.ts","../../../src/exceptions.ts","../../../src/otel.ts","../../../src/client.ts","../../../src/adapters/nest/guard.ts","../../../src/adapters/nest/module.ts"],"names":["SetMetadata","createParamDecorator","defaultResource","resourceFromAttributes","ATTR_SERVICE_NAME","ATTR_SERVICE_NAMESPACE","NodeSDK","OTLPTraceExporter","PeriodicExportingMetricReader","OTLPMetricExporter","BatchLogRecordProcessor","OTLPLogExporter","getNodeAutoInstrumentations","logs","SeverityNumber","createRemoteJWKSet","jwtVerify","CaronteGuard","trace","UnauthorizedException","ForbiddenException","Injectable","Reflector","CaronteModule","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 = 'caronte:operation';\n\nexport interface OperationMeta {\n id: string;\n level: string;\n method: string;\n}\n\n/**\n * Marks a controller method as a caronte operation.\n *\n * @example\n * ```ts\n * @Get()\n * @Operation('tasks:list', 'private')\n * listTasks(@CaronteUser() 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 CaronteUser = createParamDecorator(\n (_data: unknown, ctx: ExecutionContext): TokenClaims | undefined =>\n ctx.switchToHttp().getRequest().caronteUser,\n);","export class CaronteError extends Error {\n constructor(message: string) {\n super(message);\n this.name = this.constructor.name;\n }\n}\n\nexport class CaronteAuthError extends CaronteError {}\nexport class CaronteTokenError extends CaronteError {}\nexport class CaronteForbiddenError extends CaronteError {}\nexport class CaronteSyncError extends CaronteError {}\nexport class CaronteConfigError extends CaronteError {}","import { NodeSDK } from '@opentelemetry/sdk-node';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';\nimport { BatchLogRecordProcessor } from '@opentelemetry/sdk-logs';\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\nimport { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';\nimport { ATTR_SERVICE_NAME, ATTR_SERVICE_NAMESPACE } from '@opentelemetry/semantic-conventions';\nimport { logs, SeverityNumber } from '@opentelemetry/api-logs';\n\nexport interface OtelInitOptions {\n otelCollectorUrl: string;\n appId: string;\n realmId: string;\n}\n\nlet started = false;\n\n/**\n * Best-effort OTel bootstrap: a misconfigured or unreachable collector must\n * never break CaronteClient.startup() (auth/JWKS still have to work), so\n * every failure here is swallowed. Guarded by `started` because NodeSDK is a\n * process-wide singleton — re-running .start() would double-register the\n * auto-instrumentations' require hooks.\n */\nexport function initOtel(options: OtelInitOptions): void {\n if (started) return;\n try {\n const base = options.otelCollectorUrl.replace(/\\/$/, '');\n const resource = defaultResource().merge(resourceFromAttributes({\n [ATTR_SERVICE_NAME]: options.appId,\n [ATTR_SERVICE_NAMESPACE]: options.realmId,\n }));\n\n const sdk = new NodeSDK({\n resource,\n traceExporter: new OTLPTraceExporter({ url: `${base}/v1/traces` }),\n metricReaders: [\n new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({ url: `${base}/v1/metrics` }),\n }),\n ],\n logRecordProcessors: [\n new BatchLogRecordProcessor({ exporter: new OTLPLogExporter({ url: `${base}/v1/logs` }) }),\n ],\n instrumentations: [getNodeAutoInstrumentations()],\n });\n sdk.start();\n started = true;\n\n // Auto-instrumentation only yields traces (and, from real HTTP traffic,\n // metrics) — nothing captures console output as OTel logs. Emit one\n // bootstrap record so the log pipeline (client -> Collector -> Loki) is\n // provably wired even before the app receives its first request.\n logs.getLogger('caronte-sdk').emit({\n severityNumber: SeverityNumber.INFO,\n body: `caronte-sdk OTel initialized for app_id=${options.appId} realm_id=${options.realmId}`,\n });\n } catch (err) {\n console.warn(`[caronte-sdk] OTel initialization skipped: ${(err as Error).message}`);\n }\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport {\n CaronteAuthError, CaronteConfigError, CaronteError,\n CaronteSyncError, CaronteTokenError,\n} from './exceptions.js';\nimport type { OperationDescriptor, OperationWithGroups, TokenClaims } from './models.js';\nimport { initOtel } from './otel.js';\nimport { getRegistry } from './registry.js';\n\nexport interface CaronteClientOptions {\n authorizerUrl: string;\n realmId: string;\n appId: string;\n secret: string;\n /** Opt-in: URL of an OTLP collector (e.g. http://localhost:4318). Omit to skip OTel entirely. */\n otelCollectorUrl?: string;\n}\n\nexport class CaronteClient {\n private readonly base: string;\n private readonly realmId: string;\n private readonly appId: string;\n private readonly secret: string;\n private readonly otelCollectorUrl?: 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: CaronteClientOptions) {\n this.base = options.authorizerUrl.replace(/\\/$/, '');\n this.realmId = options.realmId;\n this.appId = options.appId;\n this.secret = options.secret;\n this.otelCollectorUrl = options.otelCollectorUrl;\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 CaronteConfigError(\n 'No operations registered. Call registerOperation() before startup().',\n );\n }\n if (this.otelCollectorUrl) {\n initOtel({ otelCollectorUrl: this.otelCollectorUrl, appId: this.appId, realmId: this.realmId });\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 CaronteAuthError(\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 CaronteAuthError('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 CaronteSyncError(`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 CaronteError(\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 CaronteTokenError(\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 CaronteTokenError) throw err;\n throw new CaronteTokenError(`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: CaronteClientOptions): Promise<CaronteClient> {\n const client = new CaronteClient(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 CaronteAuthError('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 { trace } from '@opentelemetry/api';\nimport { CaronteClient } from '../../client.js';\nimport type { TokenClaims } from '../../models.js';\nimport { OPERATION_KEY, type OperationMeta } from './decorator.js';\n\n@Injectable()\nexport class CaronteGuard 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 CaronteGuard).\n constructor(\n @Inject(CaronteClient) private readonly client: CaronteClient,\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>; caronteUser?: TokenClaims }>();\n const span = trace.getActiveSpan();\n span?.setAttribute('caronte.operation_id', id);\n\n if (level === 'public') {\n span?.setAttribute('caronte.permission_result', 'public');\n return true;\n }\n\n const auth = request.headers['authorization'] ?? '';\n const [scheme, token] = auth.split(' ');\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n span?.setAttribute('caronte.permission_result', 'unauthorized');\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 span?.setAttribute('caronte.permission_result', 'unauthorized');\n throw new UnauthorizedException('Invalid token.');\n }\n request.caronteUser = claims;\n span?.setAttribute('caronte.user', claims.sub);\n\n const allowed = this.client.checkPermission(claims, id, method);\n span?.setAttribute('caronte.permission_result', allowed ? 'allowed' : 'forbidden');\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 { CaronteClient, type CaronteClientOptions } from '../../client.js';\nimport { getRegistry } from '../../registry.js';\nimport { CaronteGuard } from './guard.js';\n\nexport interface CaronteModuleOptions extends CaronteClientOptions {}\n\n@Module({})\nexport class CaronteModule {\n /**\n * Register the caronte module globally.\n *\n * Creates the `CaronteClient`, bootstraps it (authenticate + sync + fetch),\n * and provides `CaronteGuard` for injection.\n *\n * @example\n * ```ts\n * // app.module.ts\n * @Module({\n * imports: [\n * CaronteModule.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 * @remarks\n * If `options.otelCollectorUrl` is set, this alone does **not** get you\n * request tracing: `NestFactory.create()` requires express/fastify\n * internally to build the HTTP adapter *before* this module's provider\n * factory (and its `startup()`/`initOtel()` call) ever runs, so\n * auto-instrumentation attaches too late. Call `initOtel()` from\n * `@caronte-sdk/node` yourself, before `import { NestFactory } from\n * '@nestjs/core'` in `main.ts` (CommonJS only — `require()` order is\n * preserved textually there). See the README's \"Running with\n * otelCollectorUrl on NestJS\" section for the full example. The call\n * this module makes is a harmless idempotent no-op either way.\n */\n static forRootAsync(options: CaronteModuleOptions): DynamicModule {\n return {\n module: CaronteModule,\n global: true,\n providers: [\n Reflector,\n {\n provide: CaronteClient,\n useFactory: async () => {\n const client = new CaronteClient(options);\n for (const op of getRegistry()) client.registerOperation(op);\n await client.startup();\n return client;\n },\n },\n CaronteGuard,\n ],\n exports: [CaronteClient, CaronteGuard],\n };\n }\n}"]}
|
|
@@ -53,6 +53,18 @@ declare class CaronteModule {
|
|
|
53
53
|
* })
|
|
54
54
|
* export class AppModule {}
|
|
55
55
|
* ```
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* If `options.otelCollectorUrl` is set, this alone does **not** get you
|
|
59
|
+
* request tracing: `NestFactory.create()` requires express/fastify
|
|
60
|
+
* internally to build the HTTP adapter *before* this module's provider
|
|
61
|
+
* factory (and its `startup()`/`initOtel()` call) ever runs, so
|
|
62
|
+
* auto-instrumentation attaches too late. Call `initOtel()` from
|
|
63
|
+
* `@caronte-sdk/node` yourself, before `import { NestFactory } from
|
|
64
|
+
* '@nestjs/core'` in `main.ts` (CommonJS only — `require()` order is
|
|
65
|
+
* preserved textually there). See the README's "Running with
|
|
66
|
+
* otelCollectorUrl on NestJS" section for the full example. The call
|
|
67
|
+
* this module makes is a harmless idempotent no-op either way.
|
|
56
68
|
*/
|
|
57
69
|
static forRootAsync(options: CaronteModuleOptions): DynamicModule;
|
|
58
70
|
}
|
|
@@ -53,6 +53,18 @@ declare class CaronteModule {
|
|
|
53
53
|
* })
|
|
54
54
|
* export class AppModule {}
|
|
55
55
|
* ```
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* If `options.otelCollectorUrl` is set, this alone does **not** get you
|
|
59
|
+
* request tracing: `NestFactory.create()` requires express/fastify
|
|
60
|
+
* internally to build the HTTP adapter *before* this module's provider
|
|
61
|
+
* factory (and its `startup()`/`initOtel()` call) ever runs, so
|
|
62
|
+
* auto-instrumentation attaches too late. Call `initOtel()` from
|
|
63
|
+
* `@caronte-sdk/node` yourself, before `import { NestFactory } from
|
|
64
|
+
* '@nestjs/core'` in `main.ts` (CommonJS only — `require()` order is
|
|
65
|
+
* preserved textually there). See the README's "Running with
|
|
66
|
+
* otelCollectorUrl on NestJS" section for the full example. The call
|
|
67
|
+
* this module makes is a harmless idempotent no-op either way.
|
|
56
68
|
*/
|
|
57
69
|
static forRootAsync(options: CaronteModuleOptions): DynamicModule;
|
|
58
70
|
}
|
|
@@ -88,6 +88,18 @@ var CaronteModule = class {
|
|
|
88
88
|
* })
|
|
89
89
|
* export class AppModule {}
|
|
90
90
|
* ```
|
|
91
|
+
*
|
|
92
|
+
* @remarks
|
|
93
|
+
* If `options.otelCollectorUrl` is set, this alone does **not** get you
|
|
94
|
+
* request tracing: `NestFactory.create()` requires express/fastify
|
|
95
|
+
* internally to build the HTTP adapter *before* this module's provider
|
|
96
|
+
* factory (and its `startup()`/`initOtel()` call) ever runs, so
|
|
97
|
+
* auto-instrumentation attaches too late. Call `initOtel()` from
|
|
98
|
+
* `@caronte-sdk/node` yourself, before `import { NestFactory } from
|
|
99
|
+
* '@nestjs/core'` in `main.ts` (CommonJS only — `require()` order is
|
|
100
|
+
* preserved textually there). See the README's "Running with
|
|
101
|
+
* otelCollectorUrl on NestJS" section for the full example. The call
|
|
102
|
+
* this module makes is a harmless idempotent no-op either way.
|
|
91
103
|
*/
|
|
92
104
|
static forRootAsync(options) {
|
|
93
105
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/nest/decorator.ts","../../../src/adapters/nest/guard.ts","../../../src/adapters/nest/module.ts"],"names":["Reflector"],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/nest/decorator.ts","../../../src/adapters/nest/guard.ts","../../../src/adapters/nest/module.ts"],"names":["Reflector"],"mappings":"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","file":"index.js","sourcesContent":["import { createParamDecorator, ExecutionContext, SetMetadata } from '@nestjs/common';\nimport type { TokenClaims } from '../../models.js';\nimport { detectMethod, registerOperation } from '../../registry.js';\n\nexport const OPERATION_KEY = 'caronte:operation';\n\nexport interface OperationMeta {\n id: string;\n level: string;\n method: string;\n}\n\n/**\n * Marks a controller method as a caronte operation.\n *\n * @example\n * ```ts\n * @Get()\n * @Operation('tasks:list', 'private')\n * listTasks(@CaronteUser() 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 CaronteUser = createParamDecorator(\n (_data: unknown, ctx: ExecutionContext): TokenClaims | undefined =>\n ctx.switchToHttp().getRequest().caronteUser,\n);","import {\n CanActivate, ExecutionContext, ForbiddenException,\n Inject, Injectable, UnauthorizedException,\n} from '@nestjs/common';\nimport { Reflector } from '@nestjs/core';\nimport { trace } from '@opentelemetry/api';\nimport { CaronteClient } from '../../client.js';\nimport type { TokenClaims } from '../../models.js';\nimport { OPERATION_KEY, type OperationMeta } from './decorator.js';\n\n@Injectable()\nexport class CaronteGuard 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 CaronteGuard).\n constructor(\n @Inject(CaronteClient) private readonly client: CaronteClient,\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>; caronteUser?: TokenClaims }>();\n const span = trace.getActiveSpan();\n span?.setAttribute('caronte.operation_id', id);\n\n if (level === 'public') {\n span?.setAttribute('caronte.permission_result', 'public');\n return true;\n }\n\n const auth = request.headers['authorization'] ?? '';\n const [scheme, token] = auth.split(' ');\n\n if (scheme?.toLowerCase() !== 'bearer' || !token) {\n span?.setAttribute('caronte.permission_result', 'unauthorized');\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 span?.setAttribute('caronte.permission_result', 'unauthorized');\n throw new UnauthorizedException('Invalid token.');\n }\n request.caronteUser = claims;\n span?.setAttribute('caronte.user', claims.sub);\n\n const allowed = this.client.checkPermission(claims, id, method);\n span?.setAttribute('caronte.permission_result', allowed ? 'allowed' : 'forbidden');\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 { CaronteClient, type CaronteClientOptions } from '../../client.js';\nimport { getRegistry } from '../../registry.js';\nimport { CaronteGuard } from './guard.js';\n\nexport interface CaronteModuleOptions extends CaronteClientOptions {}\n\n@Module({})\nexport class CaronteModule {\n /**\n * Register the caronte module globally.\n *\n * Creates the `CaronteClient`, bootstraps it (authenticate + sync + fetch),\n * and provides `CaronteGuard` for injection.\n *\n * @example\n * ```ts\n * // app.module.ts\n * @Module({\n * imports: [\n * CaronteModule.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 * @remarks\n * If `options.otelCollectorUrl` is set, this alone does **not** get you\n * request tracing: `NestFactory.create()` requires express/fastify\n * internally to build the HTTP adapter *before* this module's provider\n * factory (and its `startup()`/`initOtel()` call) ever runs, so\n * auto-instrumentation attaches too late. Call `initOtel()` from\n * `@caronte-sdk/node` yourself, before `import { NestFactory } from\n * '@nestjs/core'` in `main.ts` (CommonJS only — `require()` order is\n * preserved textually there). See the README's \"Running with\n * otelCollectorUrl on NestJS\" section for the full example. The call\n * this module makes is a harmless idempotent no-op either way.\n */\n static forRootAsync(options: CaronteModuleOptions): DynamicModule {\n return {\n module: CaronteModule,\n global: true,\n providers: [\n Reflector,\n {\n provide: CaronteClient,\n useFactory: async () => {\n const client = new CaronteClient(options);\n for (const op of getRegistry()) client.registerOperation(op);\n await client.startup();\n return client;\n },\n },\n CaronteGuard,\n ],\n exports: [CaronteClient, CaronteGuard],\n };\n }\n}"]}
|