@classytic/arc 2.41.1 → 2.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
- package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-tzA7CAB4.mjs} +22 -17
- package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-B6UaKRbF.mjs} +2 -2
- package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
- package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-CuCARu2B.mjs} +44 -13
- package/dist/actionPermissions-BotX1YOa.mjs +776 -0
- package/dist/audit/index.d.mts +43 -5
- package/dist/audit/index.mjs +48 -26
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +43 -13
- package/dist/auth/index.mjs +130 -155
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-DQYrkl5f.mjs} +7 -102
- package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
- package/dist/boundedMap-BULzfXYU.mjs +57 -0
- package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-CRQ8EcX5.mjs} +4 -4
- package/dist/cache/index.d.mts +22 -34
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-DbCBxlgw.mjs → caching-Cc2M1DwO.mjs} +3 -3
- package/dist/claimed-B10RTfkM.mjs +8 -0
- package/dist/cleanup/index.d.mts +6 -10
- package/dist/cleanup/index.mjs +27 -73
- package/dist/cli/commands/describe.d.mts +4 -2
- package/dist/cli/commands/describe.mjs +7 -4
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -2
- package/dist/cli/commands/init.mjs +2 -2
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-D5Ubn1fe.mjs → constants-Cu7Mx7_U.mjs} +4 -2
- package/dist/context/index.d.mts +2 -5
- package/dist/context/index.mjs +18 -38
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +8 -8
- package/dist/{core-5lazhva9.mjs → core-Cb0LjccA.mjs} +5 -4
- package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-xjqonMRO.mjs} +87 -39
- package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-zRYWw_5D.mjs} +11 -8
- package/dist/{preloadResources-f3boenVZ.mjs → createApp-D-953ZAq.mjs} +299 -390
- package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-C9cxS8zt.d.mts} +1 -1
- package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation-Bm8RjMbq.mjs} +1 -1
- package/dist/{defineResource-DxkMTjRn.mjs → defineResource-DIC7JZGU.mjs} +118 -1024
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +10 -4
- package/dist/docs/index.mjs +4 -4
- package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
- package/dist/{elevation-CkvG0LG2.mjs → elevation-DG8SrLN-.mjs} +41 -12
- package/dist/encryption/index.mjs +3 -3
- package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-BnfDviL1.mjs} +26 -5
- package/dist/{errors-BH7YU_9O.mjs → errors-CtrywMHP.mjs} +58 -23
- package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
- package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
- package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-Q6BhzHzs.mjs} +82 -21
- package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-Cdhm6ZlV.mjs} +151 -17
- package/dist/events/index.d.mts +33 -8
- package/dist/events/index.mjs +49 -53
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +139 -157
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/events/transports/redis.mjs +2 -2
- package/dist/factory/index.d.mts +32 -17
- package/dist/factory/index.mjs +213 -32
- package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DhUJ-mvo.d.mts} +11 -25
- package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
- package/dist/{fields-BHrkoF5y.mjs → fields-ToPYpMqS.mjs} +1 -1
- package/dist/filter-merge-IpGywvym.mjs +99 -0
- package/dist/{generate-BLRf2m3y.mjs → generate-DRTkLlIl.mjs} +2 -2
- package/dist/{headers-BIXWKrzQ.mjs → headers-BbkIF6vA.mjs} +2 -2
- package/dist/health-D-Ft6JM6.mjs +22 -0
- package/dist/{health-ZRHeDHXH.mjs → health-DqbsG-_w.mjs} +115 -55
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.mjs +2 -2
- package/dist/idempotency/index.d.mts +31 -7
- package/dist/idempotency/index.mjs +155 -98
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/idempotency/redis.mjs +48 -11
- package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
- package/dist/{preloadResources-CjS2OfpU.d.mts → index-C8zVGYsk.d.mts} +37 -38
- package/dist/{index-D4u76eQW.d.mts → index-CRoPtISf.d.mts} +23 -73
- package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
- package/dist/index-JdbZAIsm.d.mts +510 -0
- package/dist/{index-DHbyPo5j.d.mts → index-mqaqZNpe.d.mts} +253 -254
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +11 -11
- package/dist/{init-CpLkjU18.mjs → init-B_oUYDXI.mjs} +1 -1
- package/dist/integrations/event-gateway.d.mts +8 -3
- package/dist/integrations/event-gateway.mjs +4 -4
- package/dist/integrations/index.d.mts +3 -3
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +18 -5
- package/dist/integrations/mcp/index.d.mts +72 -59
- package/dist/integrations/mcp/index.mjs +19 -4
- package/dist/integrations/mcp/testing.d.mts +2 -2
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +78 -136
- package/dist/integrations/streamline.mjs +116 -54
- package/dist/integrations/webhooks.d.mts +60 -120
- package/dist/integrations/webhooks.mjs +36 -80
- package/dist/integrations/websocket-pushref-redis.d.mts +1 -1
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.d.mts +3 -3
- package/dist/integrations/websocket.mjs +2 -2
- package/dist/{interface-DEWNOMza.d.mts → interface-C0395yUN.d.mts} +13 -1
- package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-B4YVGcql.mjs} +2 -2
- package/dist/{keys-cpZCtcIE.mjs → keys-B2KtgMLJ.mjs} +7 -18
- package/dist/{loadResources-BPfWiI5s.mjs → loadResources-Dn4lalw2.mjs} +3 -3
- package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-3sLYbuse.mjs} +2 -2
- package/dist/logger/index.d.mts +1 -8
- package/dist/logger/index.mjs +3 -153
- package/dist/logger-DXjfIqjV.mjs +160 -0
- package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-C08HalN5.mjs} +433 -170
- package/dist/{memory-Iotz0cCx.mjs → memory-9Cp7611C.mjs} +36 -34
- package/dist/{metrics-NMsmpRmY.mjs → metrics-CWI11eRu.mjs} +39 -72
- package/dist/middleware/index.d.mts +2 -2
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.mjs +2 -2
- package/dist/{module-DpLJG2_N.mjs → module-BSvOQC7E.mjs} +8 -8
- package/dist/multiTenant-cY0FkDiA.d.mts +104 -0
- package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-CXM2a-Dy.mjs} +46 -7
- package/dist/{openapi-CmFf3yq_.mjs → openapi-DT_G4VhY.mjs} +48 -10
- package/dist/outbox-admin/index.d.mts +3 -3
- package/dist/outbox-admin/index.mjs +6 -18
- package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Bjgzl6tg.mjs} +203 -33
- package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +8 -6
- package/dist/{permissions-D8TBH44E.mjs → permissions-Cm0uYHvd.mjs} +149 -33
- package/dist/{pipe-FMWNheSO.mjs → pipe-BqeGT6UO.mjs} +2 -2
- package/dist/pipeline/index.d.mts +2 -2
- package/dist/pipeline/index.mjs +2 -2
- package/dist/plan-FVR6LP59.mjs +565 -0
- package/dist/{BaseController-CYEwjyjN.mjs → plugin-BccET1tL.mjs} +1256 -345
- package/dist/plugins/index.d.mts +14 -11
- package/dist/plugins/index.mjs +44 -22
- package/dist/plugins/response-cache.mjs +8 -14
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-CXWZIzTv.mjs → pluralize-CVIOcgMF.mjs} +1 -1
- package/dist/presets/filesUpload.d.mts +2 -2
- package/dist/presets/filesUpload.mjs +5 -5
- package/dist/presets/index.d.mts +26 -31
- package/dist/presets/index.mjs +4 -4
- package/dist/presets/multiTenant.d.mts +2 -107
- package/dist/presets/multiTenant.mjs +22 -162
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-ZJSPgmT2.mjs → presets-Cpvj6fGO.mjs} +99 -107
- package/dist/{projection-BzIgzoKZ.mjs → projection-Ce4aQhQk.mjs} +2 -2
- package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
- package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
- package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-CFWNH8aT.mjs} +12 -14
- package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-C4O-kPm0.mjs} +1 -1
- package/dist/{realtime-8tIQWZz4.mjs → realtime-DmPE9S54.mjs} +25 -21
- package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
- package/dist/{redis-Bzi1y3F9.d.mts → redis-vLvtcGy_.d.mts} +13 -24
- package/dist/redisShapes-CQksY67q.d.mts +55 -0
- package/dist/registry/index.d.mts +9 -4
- package/dist/registry/index.mjs +4 -4
- package/dist/{registry-DNkgGQcK.mjs → registry-Bcz9G1bh.mjs} +10 -8
- package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-qODa7KJQ.mjs} +1 -1
- package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-CG_VtVgS.mjs} +2 -2
- package/dist/{requestContext-cDkAUr-P.mjs → requestContext-Dsu9P1bV.mjs} +1 -1
- package/dist/requirement-CbiLdQ1n.d.mts +22 -0
- package/dist/requirement-KDdoRcOP.mjs +35 -0
- package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
- package/dist/resourceRateLimit-dSjVr1pk.mjs +180 -0
- package/dist/{rolldown-runtime-eysyzFAF.mjs → rolldown-runtime-D1w9Y1VJ.mjs} +1 -1
- package/dist/routeValidator-D36SW8qt.mjs +70 -0
- package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-0tccjRlj.mjs} +1 -1
- package/dist/{schedules-j6uXXAeJ.mjs → schedules-C-OpmHBq.mjs} +46 -37
- package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BORek3O-.mjs} +2 -2
- package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-C7Vbp71I.mjs} +2 -2
- package/dist/schemas/index.d.mts +10 -0
- package/dist/schemas/index.mjs +8 -3
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +6 -6
- package/dist/{scope-BUi1xV1I.mjs → scope-DQthe88b.mjs} +4 -4
- package/dist/shutdown-MqA81z_P.mjs +59 -0
- package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-auW8QjXN.mjs} +1 -1
- package/dist/{sse-BeqVKQKu.mjs → sse-CYzQBVFe.mjs} +11 -15
- package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-B5_Afiqn.mjs} +2 -2
- package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-BOzk-CuX.mjs} +1 -1
- package/dist/{streaming-IcRFjWQU.mjs → streaming-DjTQhZrN.mjs} +1 -1
- package/dist/subscriberIdentity-CW39uA8G.mjs +28 -0
- package/dist/tenancy--ed9eH_z.mjs +43 -0
- package/dist/tenantPreparation-BKon6Yox.mjs +67 -0
- package/dist/testing/cleanupStoreContract.mjs +1 -1
- package/dist/testing/index.d.mts +193 -175
- package/dist/testing/index.mjs +286 -212
- package/dist/testing/outboxStoreContract.mjs +137 -2
- package/dist/testing/requiredPorts.d.mts +17 -0
- package/dist/testing/requiredPorts.mjs +65 -0
- package/dist/testing/storageContract.mjs +1 -1
- package/dist/timing-qczZ0YC-.mjs +46 -0
- package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-DjFkrNG6.mjs} +1 -1
- package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-CySF12G-.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-CWQn9-IC.d.mts → types-B4Aq4Sdj.d.mts} +22 -9
- package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
- package/dist/{types-CgenB1gv.mjs → types-Bk9NOgOC.mjs} +4 -4
- package/dist/usage/index.d.mts +2 -3
- package/dist/usage/index.mjs +5 -5
- package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-aklawRaK.mjs} +1 -1
- package/dist/utils/index.d.mts +84 -223
- package/dist/utils/index.mjs +13 -12
- package/dist/{utils-CxcctrAh.mjs → utils-ec1oTo1n.mjs} +315 -404
- package/dist/{validate-DrYWnOzI.mjs → validate-9yzHC1e2.mjs} +6 -14
- package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
- package/dist/{versioning-DKkT4hNJ.mjs → versioning-fhhWHV74.mjs} +4 -4
- package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
- package/dist/{workScope-CxKqoIFn.mjs → workScope-zpPyge4t.mjs} +2 -2
- package/package.json +16 -12
- package/skills/arc/SKILL.md +13 -4
- package/skills/arc/references/auth.md +8 -5
- package/skills/arc/references/integrations.md +1 -1
- package/skills/arc/references/mcp.md +8 -6
- package/skills/arc/references/multi-tenancy.md +19 -14
- package/skills/arc/references/production.md +27 -10
- package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
- package/dist/index-CFfLKMH4.d.mts +0 -290
- package/dist/interface-YzIbF7Ii.mjs +0 -17
- package/dist/redis-stream-BPKscsTB.d.mts +0 -260
- package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
- package/dist/sync/changelog.d.mts +0 -3
- package/dist/sync/changelog.mjs +0 -3
package/dist/audit/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import { d as UserBase } from "../base-
|
|
3
|
-
import "../index-
|
|
2
|
+
import { d as UserBase } from "../base-CZyixEQR.mjs";
|
|
3
|
+
import "../index-mqaqZNpe.mjs";
|
|
4
4
|
import { FastifyPluginAsync } from "fastify";
|
|
5
5
|
import { RepositoryLike } from "@classytic/repo-core/adapter";
|
|
6
6
|
//#region src/audit/stores/interface.d.ts
|
|
@@ -37,6 +37,8 @@ interface AuditEntry {
|
|
|
37
37
|
}
|
|
38
38
|
interface AuditContext {
|
|
39
39
|
user?: UserBase;
|
|
40
|
+
/** The actor from the request's VALIDATED scope (user or service client). Wins over `user`. */
|
|
41
|
+
actorId?: string;
|
|
40
42
|
organizationId?: string;
|
|
41
43
|
requestId?: string;
|
|
42
44
|
ipAddress?: string;
|
|
@@ -191,8 +193,13 @@ declare module "fastify" {
|
|
|
191
193
|
audit: AuditLogger;
|
|
192
194
|
}
|
|
193
195
|
interface FastifyRequest {
|
|
194
|
-
/**
|
|
196
|
+
/**
|
|
197
|
+
* Audit context for the current request. The actor and organization are read from
|
|
198
|
+
* the VALIDATED scope when this is read — never captured before auth ran.
|
|
199
|
+
*/
|
|
195
200
|
auditContext?: AuditContext;
|
|
201
|
+
/** Extra fields a handler attaches to the audit row arc writes for this request. */
|
|
202
|
+
auditMetadata?: Record<string, unknown>;
|
|
196
203
|
}
|
|
197
204
|
}
|
|
198
205
|
interface AuditLogger {
|
|
@@ -206,6 +213,11 @@ interface AuditLogger {
|
|
|
206
213
|
restore: (resource: string, documentId: string, data: Record<string, unknown>, context?: AuditContext) => Promise<void>;
|
|
207
214
|
/** Log a custom action */
|
|
208
215
|
custom: (resource: string, documentId: string, action: string, data?: Record<string, unknown>, context?: AuditContext) => Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* A logger bound to one request: every entry's actor and organization come from that
|
|
218
|
+
* request's validated scope, so a caller can neither forget nor forge them.
|
|
219
|
+
*/
|
|
220
|
+
forRequest: (request: AuditRequestLike) => RequestAuditLogger;
|
|
209
221
|
/** Query audit logs (if stores support it) */
|
|
210
222
|
query: (options: AuditQueryOptions) => Promise<AuditEntry[]>;
|
|
211
223
|
/**
|
|
@@ -215,7 +227,33 @@ interface AuditLogger {
|
|
|
215
227
|
*/
|
|
216
228
|
purge: (cutoff: Date) => Promise<number>;
|
|
217
229
|
}
|
|
218
|
-
|
|
230
|
+
/** {@link AuditLogger} writes with the context bound to one request. */
|
|
231
|
+
interface RequestAuditLogger {
|
|
232
|
+
create: (resource: string, documentId: string, data: Record<string, unknown>) => Promise<void>;
|
|
233
|
+
update: (resource: string, documentId: string, before: Record<string, unknown>, after: Record<string, unknown>) => Promise<void>;
|
|
234
|
+
delete: (resource: string, documentId: string, data: Record<string, unknown>) => Promise<void>;
|
|
235
|
+
restore: (resource: string, documentId: string, data: Record<string, unknown>) => Promise<void>;
|
|
236
|
+
custom: (resource: string, documentId: string, action: string, data?: Record<string, unknown>) => Promise<void>;
|
|
237
|
+
}
|
|
238
|
+
/** What {@link auditContextOf} reads — a FastifyRequest, or arc's `IRequestContext`. */
|
|
239
|
+
interface AuditRequestLike {
|
|
240
|
+
readonly scope?: unknown;
|
|
241
|
+
readonly user?: unknown;
|
|
242
|
+
readonly id?: string;
|
|
243
|
+
readonly ip?: string;
|
|
244
|
+
readonly headers?: Record<string, unknown>;
|
|
245
|
+
readonly method?: string;
|
|
246
|
+
readonly url?: string;
|
|
247
|
+
readonly routeOptions?: {
|
|
248
|
+
readonly url?: string;
|
|
249
|
+
};
|
|
250
|
+
readonly metadata?: unknown;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The audit context of a request, from its VALIDATED scope: the actor is the scope's user
|
|
254
|
+
* (or service client) and the organization is the scope's active organization.
|
|
255
|
+
*/
|
|
256
|
+
declare function auditContextOf(request: AuditRequestLike): AuditContext;
|
|
219
257
|
declare const _default: FastifyPluginAsync<AuditPluginOptions>;
|
|
220
258
|
//#endregion
|
|
221
259
|
//#region src/audit/repository-audit-adapter.d.ts
|
|
@@ -259,4 +297,4 @@ declare class MemoryAuditStore implements AuditStore {
|
|
|
259
297
|
clear(): void;
|
|
260
298
|
}
|
|
261
299
|
//#endregion
|
|
262
|
-
export { type AuditAction, type AuditContext, type AuditEntry, type AuditLogger, type AuditPluginOptions, type AuditQueryOptions, type AuditStore, type AuditStoreOptions, MemoryAuditStore, type MemoryAuditStoreOptions,
|
|
300
|
+
export { type AuditAction, type AuditContext, type AuditEntry, type AuditLogger, type AuditPluginOptions, type AuditQueryOptions, type AuditRequestLike, type AuditStore, type AuditStoreOptions, MemoryAuditStore, type MemoryAuditStoreOptions, type RepositoryAuditStoreOptions, type RequestAuditLogger, auditContextOf, _default as auditPlugin, createAuditEntry, repositoryAsAuditStore };
|
package/dist/audit/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
/*! @classytic/arc v2.43.0 | MIT | https://classytic.com */
|
|
2
|
+
import { g as getUserId, i as getClientId } from "../types-Bk9NOgOC.mjs";
|
|
3
|
+
import { t as transactionContext } from "../transactionContext-DjFkrNG6.mjs";
|
|
4
|
+
import { n as declareRuntimeCapability } from "../runtimeCapabilities-0tccjRlj.mjs";
|
|
4
5
|
import { and, anyOf, eq, gte, lt, lte } from "@classytic/repo-core/filter";
|
|
5
6
|
import fp from "fastify-plugin";
|
|
6
7
|
//#region src/audit/repository-audit-adapter.ts
|
|
@@ -86,7 +87,7 @@ function createAuditEntry(resource, documentId, action, context, data) {
|
|
|
86
87
|
resource,
|
|
87
88
|
documentId,
|
|
88
89
|
action,
|
|
89
|
-
userId: extractUserId(context.user),
|
|
90
|
+
userId: context.actorId ?? extractUserId(context.user),
|
|
90
91
|
organizationId: context.organizationId,
|
|
91
92
|
before: data?.before,
|
|
92
93
|
after: data?.after,
|
|
@@ -182,6 +183,7 @@ const auditPlugin = async (fastify, opts = {}) => {
|
|
|
182
183
|
if (!enabled) {
|
|
183
184
|
fastify.decorate("audit", createNoopLogger());
|
|
184
185
|
fastify.decorateRequest("auditContext", void 0);
|
|
186
|
+
fastify.decorateRequest("auditMetadata", void 0);
|
|
185
187
|
fastify.log?.debug?.("Audit plugin disabled");
|
|
186
188
|
return;
|
|
187
189
|
}
|
|
@@ -220,6 +222,16 @@ const auditPlugin = async (fastify, opts = {}) => {
|
|
|
220
222
|
...data
|
|
221
223
|
} }));
|
|
222
224
|
},
|
|
225
|
+
forRequest(request) {
|
|
226
|
+
const ctx = () => auditContextOf(request);
|
|
227
|
+
return {
|
|
228
|
+
create: (resource, documentId, data) => audit.create(resource, documentId, data, ctx()),
|
|
229
|
+
update: (resource, documentId, before, after) => audit.update(resource, documentId, before, after, ctx()),
|
|
230
|
+
delete: (resource, documentId, data) => audit.delete(resource, documentId, data, ctx()),
|
|
231
|
+
restore: (resource, documentId, data) => audit.restore(resource, documentId, data, ctx()),
|
|
232
|
+
custom: (resource, documentId, action, data) => audit.custom(resource, documentId, action, data, ctx())
|
|
233
|
+
};
|
|
234
|
+
},
|
|
223
235
|
async query(options) {
|
|
224
236
|
for (const store of stores) if (store.query) return store.query(options);
|
|
225
237
|
return [];
|
|
@@ -231,27 +243,10 @@ const auditPlugin = async (fastify, opts = {}) => {
|
|
|
231
243
|
}
|
|
232
244
|
};
|
|
233
245
|
fastify.decorate("audit", audit);
|
|
234
|
-
fastify.decorateRequest("auditContext",
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const scope = request.scope;
|
|
239
|
-
request.auditContext = {
|
|
240
|
-
user,
|
|
241
|
-
organizationId: scope?.kind === "member" ? scope.organizationId : scope?.kind === "elevated" ? scope.organizationId : void 0,
|
|
242
|
-
requestId: request.id,
|
|
243
|
-
ipAddress: request.ip,
|
|
244
|
-
userAgent: request.headers["user-agent"],
|
|
245
|
-
endpoint: void 0,
|
|
246
|
-
duration: void 0
|
|
247
|
-
};
|
|
248
|
-
});
|
|
249
|
-
fastify.addHook("onResponse", async (request, reply) => {
|
|
250
|
-
if (request.auditContext) {
|
|
251
|
-
request.auditContext.endpoint = `${request.method} ${request.routeOptions?.url ?? request.url}`;
|
|
252
|
-
request.auditContext.duration = Math.round(reply.elapsedTime);
|
|
253
|
-
}
|
|
254
|
-
});
|
|
246
|
+
fastify.decorateRequest("auditContext", { getter() {
|
|
247
|
+
return auditContextOf(this);
|
|
248
|
+
} });
|
|
249
|
+
fastify.decorateRequest("auditMetadata", void 0);
|
|
255
250
|
const retention = opts.retention;
|
|
256
251
|
let retentionTimer = null;
|
|
257
252
|
if (retention) {
|
|
@@ -307,8 +302,10 @@ const auditPlugin = async (fastify, opts = {}) => {
|
|
|
307
302
|
} else if (excludeResources.has(ctx.resource)) return;
|
|
308
303
|
const docId = autoAuditExtractId(ctx.result);
|
|
309
304
|
const scope = ctx.context?._scope;
|
|
305
|
+
const scopedActor = scope ? getUserId(scope) ?? getClientId(scope) : void 0;
|
|
310
306
|
const auditCtx = {
|
|
311
307
|
user: ctx.user,
|
|
308
|
+
...scopedActor ? { actorId: String(scopedActor) } : {},
|
|
312
309
|
organizationId: scope ? autoAuditGetOrgId(scope) : void 0
|
|
313
310
|
};
|
|
314
311
|
try {
|
|
@@ -331,6 +328,24 @@ const auditPlugin = async (fastify, opts = {}) => {
|
|
|
331
328
|
}
|
|
332
329
|
fastify.log?.debug?.({ stores: stores.map((s) => s.name) }, "Audit plugin enabled");
|
|
333
330
|
};
|
|
331
|
+
/**
|
|
332
|
+
* The audit context of a request, from its VALIDATED scope: the actor is the scope's user
|
|
333
|
+
* (or service client) and the organization is the scope's active organization.
|
|
334
|
+
*/
|
|
335
|
+
function auditContextOf(request) {
|
|
336
|
+
const scope = request.metadata?._scope ?? request.scope;
|
|
337
|
+
const actorId = scope ? getUserId(scope) ?? getClientId(scope) : void 0;
|
|
338
|
+
const userAgent = request.headers?.["user-agent"];
|
|
339
|
+
return {
|
|
340
|
+
user: request.user,
|
|
341
|
+
...actorId ? { actorId: String(actorId) } : {},
|
|
342
|
+
organizationId: scope ? autoAuditGetOrgId(scope) : void 0,
|
|
343
|
+
requestId: request.id,
|
|
344
|
+
ipAddress: request.ip,
|
|
345
|
+
userAgent: typeof userAgent === "string" ? userAgent : void 0,
|
|
346
|
+
endpoint: request.method && request.routeOptions?.url ? `${request.method} ${request.routeOptions.url}` : void 0
|
|
347
|
+
};
|
|
348
|
+
}
|
|
334
349
|
/** Extract document ID from a result */
|
|
335
350
|
function autoAuditExtractId(doc) {
|
|
336
351
|
if (!doc || typeof doc !== "object") return "";
|
|
@@ -361,6 +376,13 @@ function createNoopLogger() {
|
|
|
361
376
|
delete: noop,
|
|
362
377
|
restore: noop,
|
|
363
378
|
custom: noop,
|
|
379
|
+
forRequest: () => ({
|
|
380
|
+
create: noop,
|
|
381
|
+
update: noop,
|
|
382
|
+
delete: noop,
|
|
383
|
+
restore: noop,
|
|
384
|
+
custom: noop
|
|
385
|
+
}),
|
|
364
386
|
query: async () => [],
|
|
365
387
|
purge: async () => 0,
|
|
366
388
|
_noop: true
|
|
@@ -372,4 +394,4 @@ var auditPlugin_default = fp(auditPlugin, {
|
|
|
372
394
|
dependencies: ["arc-core"]
|
|
373
395
|
});
|
|
374
396
|
//#endregion
|
|
375
|
-
export { MemoryAuditStore, auditPlugin_default as auditPlugin,
|
|
397
|
+
export { MemoryAuditStore, auditContextOf, auditPlugin_default as auditPlugin, createAuditEntry, repositoryAsAuditStore };
|
package/dist/auth/audit.mjs
CHANGED
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { i as RequestScope } from "../types-Ddl9OjmE.mjs";
|
|
3
|
+
import { l as PermissionCheck } from "../base-CZyixEQR.mjs";
|
|
4
|
+
import { At as AuthHelpers, jt as AuthPluginOptions } from "../index-mqaqZNpe.mjs";
|
|
4
5
|
import { t as ExternalOpenApiPaths } from "../externalPaths-CmGOxOtD.mjs";
|
|
5
6
|
import { a as SessionManagerOptions, c as createSessionManager, i as SessionData, n as MemorySessionStoreOptions, o as SessionManagerResult, r as SessionCookieOptions, s as SessionStore, t as MemorySessionStore } from "../sessionManager-qimlKV0P.mjs";
|
|
6
7
|
import { FastifyPluginAsync, FastifyReply as FastifyReply$1, FastifyRequest } from "fastify";
|
|
@@ -17,7 +18,6 @@ declare module "fastify" {
|
|
|
17
18
|
auth: AuthHelpers;
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
declare const authPlugin: FastifyPluginAsync<AuthPluginOptions>;
|
|
21
21
|
declare const _default: FastifyPluginAsync<AuthPluginOptions>;
|
|
22
22
|
//#endregion
|
|
23
23
|
//#region src/auth/betterAuth.d.ts
|
|
@@ -50,6 +50,30 @@ interface BetterAuthAdapterOptions {
|
|
|
50
50
|
* @default false
|
|
51
51
|
*/
|
|
52
52
|
orgContext?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Effective roles in the active organization — the seam for an organization HIERARCHY (roles held
|
|
55
|
+
* at a parent, e.g. a head office, apply in its child organizations). Called with the caller's own
|
|
56
|
+
* membership roles there (`null` when not a member); returns the roles the request carries, or
|
|
57
|
+
* `null` to leave it non-member. Requires `orgContext`.
|
|
58
|
+
*/
|
|
59
|
+
resolveOrgRoles?: (input: {
|
|
60
|
+
userId: string;
|
|
61
|
+
organizationId: string;
|
|
62
|
+
memberRoles: readonly string[] | null;
|
|
63
|
+
}) => readonly string[] | null | Promise<readonly string[] | null>;
|
|
64
|
+
/**
|
|
65
|
+
* Where the caller's own membership roles come from. Default `'better-auth'`: arc asks Better
|
|
66
|
+
* Auth (`getActiveMember`, then `getActiveMemberRole`) and passes the answer to `resolveOrgRoles`
|
|
67
|
+
* as `memberRoles`.
|
|
68
|
+
*
|
|
69
|
+
* `'resolver'`: `resolveOrgRoles` reads membership itself, so arc skips Better Auth's lookup — one
|
|
70
|
+
* fewer membership read per authenticated request — and calls it with `memberRoles: null`. Choose
|
|
71
|
+
* it ONLY for a resolver that never reads `memberRoles`; one that extends them would lose them.
|
|
72
|
+
* Requires `resolveOrgRoles`.
|
|
73
|
+
*
|
|
74
|
+
* @default 'better-auth'
|
|
75
|
+
*/
|
|
76
|
+
memberLookup?: "better-auth" | "resolver";
|
|
53
77
|
/**
|
|
54
78
|
* OpenAPI documentation for auth endpoints.
|
|
55
79
|
* - `true` (default): auto-extract from auth.api if available
|
|
@@ -86,16 +110,20 @@ interface BetterAuthAdapterOptions {
|
|
|
86
110
|
*/
|
|
87
111
|
exposeAuthErrors?: boolean;
|
|
88
112
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
113
|
+
* Credentials other than a session, by `Authorization` scheme (RFC 7235) — a paired device, an
|
|
114
|
+
* API key. A request presenting a registered scheme is authenticated by its verifier ONLY: the
|
|
115
|
+
* scope it returns (usually `{ kind: 'service', … }`) is installed; `null` is a 401. Gate such
|
|
116
|
+
* routes with `requireServiceScope(...)`. `Bearer` is the session's and cannot be registered.
|
|
92
117
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
*
|
|
118
|
+
* @example
|
|
119
|
+
* credentials: { Device: (value) => verifyDevice(value) } // Authorization: Device <sn>:<token>
|
|
120
|
+
*/
|
|
121
|
+
credentials?: Readonly<Record<string, CredentialVerifier>>;
|
|
122
|
+
/**
|
|
123
|
+
* Per-route `@fastify/rate-limit` config for the auth catch-all. No default:
|
|
124
|
+
* the same route serves the chatty `get-session` heartbeat, so a strict
|
|
125
|
+
* login-style limit would 429 every SPA that polls sessions. Pick a ceiling
|
|
126
|
+
* above your poll cadence, or exempt the heartbeat:
|
|
99
127
|
*
|
|
100
128
|
* @example
|
|
101
129
|
* ```ts
|
|
@@ -173,6 +201,8 @@ declare module "fastify" {
|
|
|
173
201
|
* fastify.get('/me', { preHandler: [authenticate] }, handler);
|
|
174
202
|
* ```
|
|
175
203
|
*/
|
|
204
|
+
/** Verifies one credential scheme's value; the scope to install, or `null` when it is not valid. */
|
|
205
|
+
type CredentialVerifier = (credentials: string, request: FastifyRequest) => Promise<RequestScope | null>;
|
|
176
206
|
declare function createBetterAuthAdapter(options: BetterAuthAdapterOptions): BetterAuthAdapterResult;
|
|
177
207
|
//#endregion
|
|
178
208
|
//#region src/auth/betterAuthOpenApi.d.ts
|
|
@@ -290,4 +320,4 @@ interface MirrorTrustedOriginsOptions {
|
|
|
290
320
|
*/
|
|
291
321
|
declare function mirrorTrustedOriginsFromCors(options: MirrorTrustedOriginsOptions): string[];
|
|
292
322
|
//#endregion
|
|
293
|
-
export { type AuthPluginOptions, type BetterAuthAdapterOptions, type BetterAuthAdapterResult, type BetterAuthHandler, type BetterAuthOpenApiOptions, type CorsOriginsConfig, MemorySessionStore, type MemorySessionStoreOptions, type MirrorTrustedOriginsOptions, type SessionCookieOptions, type SessionData, type SessionManagerOptions, type SessionManagerResult, type SessionStore, _default as authPlugin,
|
|
323
|
+
export { type AuthPluginOptions, type BetterAuthAdapterOptions, type BetterAuthAdapterResult, type BetterAuthHandler, type BetterAuthOpenApiOptions, type CorsOriginsConfig, type CredentialVerifier, MemorySessionStore, type MemorySessionStoreOptions, type MirrorTrustedOriginsOptions, type SessionCookieOptions, type SessionData, type SessionManagerOptions, type SessionManagerResult, type SessionStore, _default as authPlugin, createBetterAuthAdapter, createSessionManager, extractBetterAuthOpenApi, mirrorTrustedOriginsFromCors };
|