@endora-commerce/mod-auth 0.0.0-stage → 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -2
  3. package/dist/backend/entities/session.entity.d.ts +31 -0
  4. package/dist/backend/entities/session.entity.d.ts.map +1 -0
  5. package/dist/backend/entities/session.entity.js +95 -0
  6. package/dist/backend/entities/session.entity.js.map +1 -0
  7. package/dist/backend/index.d.ts +120 -0
  8. package/dist/backend/index.d.ts.map +1 -0
  9. package/dist/backend/index.js +194 -0
  10. package/dist/backend/index.js.map +1 -0
  11. package/dist/backend/plugin.d.ts +41 -0
  12. package/dist/backend/plugin.d.ts.map +1 -0
  13. package/dist/backend/plugin.js +164 -0
  14. package/dist/backend/plugin.js.map +1 -0
  15. package/dist/backend/require-admin.d.ts +35 -0
  16. package/dist/backend/require-admin.d.ts.map +1 -0
  17. package/dist/backend/require-admin.js +50 -0
  18. package/dist/backend/require-admin.js.map +1 -0
  19. package/dist/backend/require-customer.d.ts +4 -0
  20. package/dist/backend/require-customer.d.ts.map +1 -0
  21. package/dist/backend/require-customer.js +16 -0
  22. package/dist/backend/require-customer.js.map +1 -0
  23. package/dist/backend/services/session-port.d.ts +30 -0
  24. package/dist/backend/services/session-port.d.ts.map +1 -0
  25. package/dist/backend/services/session-port.js +93 -0
  26. package/dist/backend/services/session-port.js.map +1 -0
  27. package/dist/backend/services/session-service.d.ts +56 -0
  28. package/dist/backend/services/session-service.d.ts.map +1 -0
  29. package/dist/backend/services/session-service.js +200 -0
  30. package/dist/backend/services/session-service.js.map +1 -0
  31. package/dist/manifest.d.ts +169 -0
  32. package/dist/manifest.d.ts.map +1 -0
  33. package/dist/manifest.js +71 -0
  34. package/dist/manifest.js.map +1 -0
  35. package/docs/auth.md +42 -0
  36. package/package.json +60 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,50 @@
1
- # Temporary Holding Version
1
+ <!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # @endora-commerce/mod-auth
4
+
5
+ Authentication primitives — session cookies, bearer-token resolution, and request actor binding.
6
+
7
+ ## What this is
8
+
9
+ An **Endora Commerce module package**. Its module id is `auth` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
10
+
11
+ A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
12
+
13
+ ## Entry points
14
+
15
+ | Import | Contents |
16
+ | --- | --- |
17
+ | `@endora-commerce/mod-auth` | the module manifest — its id, version, dependencies, settings and activation |
18
+ | `@endora-commerce/mod-auth/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
19
+
20
+ ## Depends on
21
+
22
+ Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
23
+
24
+ **Endora packages**
25
+
26
+ - `@endora-commerce/contracts`
27
+ - `@endora-commerce/platform`
28
+
29
+ **Third-party**
30
+
31
+ - `@mikro-orm/core` ^6
32
+ - `@mikro-orm/postgresql` ^6
33
+ - `fastify` ^5
34
+ - `fastify-plugin` ^5
35
+ - `ioredis` ^5
36
+
37
+ ## What the tarball carries
38
+
39
+ - `dist/` — the compiled JavaScript and its type declarations
40
+ - `docs/` — the package’s own pages in the Endora Commerce documentation site
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pnpm add @endora-commerce/mod-auth
46
+ ```
47
+
48
+ ## Licence
49
+
50
+ MIT — the text is in `LICENSE`, beside this file.
@@ -0,0 +1,31 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * Persistent session row. Backed by Postgres; hot reads are cached in Redis by
4
+ * SessionService. See data-model.md § Domain 1 and R-11.
5
+ *
6
+ * `auth` is the permitted singular-exception module folder per Principle VI; this
7
+ * entity's table name remains `sessions` because class-to-table is still pluralised.
8
+ */
9
+ export declare class Session {
10
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt';
11
+ id: string;
12
+ /** Opaque token shown to the client (cookie value). Never used for lookups directly —
13
+ * we hash it before storing. The actual cookie sent to the client is `${id}.${tokenHash}`. */
14
+ tokenHash: string;
15
+ /** Null for admin-user sessions; set for customer-account sessions. */
16
+ customerAccountId?: string | null;
17
+ /** Null for customer sessions; set for admin-user sessions. */
18
+ adminUserId?: string | null;
19
+ /**
20
+ * When an admin-user is impersonating a customer, both `customerAccountId` (target)
21
+ * and `impersonatorAdminUserId` (the admin) are set — see R-12.
22
+ */
23
+ impersonatorAdminUserId?: string | null;
24
+ expiresAt: Date;
25
+ createdAt: Date;
26
+ updatedAt: Date;
27
+ lastSeenAt?: Date | null;
28
+ ipAddress?: string | null;
29
+ userAgent?: string | null;
30
+ }
31
+ //# sourceMappingURL=session.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/session.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;;;GAMG;AACH,qBAEa,OAAO;IAClB,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC;IAInD,EAAE,EAAE,MAAM,CAAgB;IAE1B;mGAC+F;IAG/F,SAAS,EAAG,MAAM,CAAC;IAEnB,uEAAuE;IAGvE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC,+DAA+D;IAG/D,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B;;;OAGG;IAEH,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAIxC,SAAS,EAAG,IAAI,CAAC;IAGjB,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;IAG7B,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAGzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B"}
@@ -0,0 +1,95 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * Persistent session row. Backed by Postgres; hot reads are cached in Redis by
15
+ * SessionService. See data-model.md § Domain 1 and R-11.
16
+ *
17
+ * `auth` is the permitted singular-exception module folder per Principle VI; this
18
+ * entity's table name remains `sessions` because class-to-table is still pluralised.
19
+ */
20
+ let Session = class Session {
21
+ [OptionalProps];
22
+ id = randomUUID();
23
+ /** Opaque token shown to the client (cookie value). Never used for lookups directly —
24
+ * we hash it before storing. The actual cookie sent to the client is `${id}.${tokenHash}`. */
25
+ tokenHash;
26
+ /** Null for admin-user sessions; set for customer-account sessions. */
27
+ customerAccountId;
28
+ /** Null for customer sessions; set for admin-user sessions. */
29
+ adminUserId;
30
+ /**
31
+ * When an admin-user is impersonating a customer, both `customerAccountId` (target)
32
+ * and `impersonatorAdminUserId` (the admin) are set — see R-12.
33
+ */
34
+ impersonatorAdminUserId;
35
+ expiresAt;
36
+ createdAt = new Date();
37
+ updatedAt = new Date();
38
+ lastSeenAt;
39
+ ipAddress;
40
+ userAgent;
41
+ };
42
+ __decorate([
43
+ PrimaryKey({ type: 'uuid' }),
44
+ __metadata("design:type", String)
45
+ ], Session.prototype, "id", void 0);
46
+ __decorate([
47
+ Property({ type: 'string', length: 128 }),
48
+ Index(),
49
+ __metadata("design:type", String)
50
+ ], Session.prototype, "tokenHash", void 0);
51
+ __decorate([
52
+ Property({ type: 'uuid', nullable: true }),
53
+ Index(),
54
+ __metadata("design:type", Object)
55
+ ], Session.prototype, "customerAccountId", void 0);
56
+ __decorate([
57
+ Property({ type: 'uuid', nullable: true }),
58
+ Index(),
59
+ __metadata("design:type", Object)
60
+ ], Session.prototype, "adminUserId", void 0);
61
+ __decorate([
62
+ Property({ type: 'uuid', nullable: true }),
63
+ __metadata("design:type", Object)
64
+ ], Session.prototype, "impersonatorAdminUserId", void 0);
65
+ __decorate([
66
+ Property({ type: 'datetime' }),
67
+ Index(),
68
+ __metadata("design:type", Date)
69
+ ], Session.prototype, "expiresAt", void 0);
70
+ __decorate([
71
+ Property({ type: 'datetime', onCreate: () => new Date() }),
72
+ __metadata("design:type", Date)
73
+ ], Session.prototype, "createdAt", void 0);
74
+ __decorate([
75
+ Property({ type: 'datetime', onUpdate: () => new Date() }),
76
+ __metadata("design:type", Date)
77
+ ], Session.prototype, "updatedAt", void 0);
78
+ __decorate([
79
+ Property({ type: 'datetime', nullable: true }),
80
+ __metadata("design:type", Object)
81
+ ], Session.prototype, "lastSeenAt", void 0);
82
+ __decorate([
83
+ Property({ type: 'string', length: 45, nullable: true }),
84
+ __metadata("design:type", Object)
85
+ ], Session.prototype, "ipAddress", void 0);
86
+ __decorate([
87
+ Property({ type: 'string', length: 255, nullable: true }),
88
+ __metadata("design:type", Object)
89
+ ], Session.prototype, "userAgent", void 0);
90
+ Session = __decorate([
91
+ GlobalEntity(),
92
+ Entity({ tableName: 'sessions' })
93
+ ], Session);
94
+ export { Session };
95
+ //# sourceMappingURL=session.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/session.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;GAMG;AAGI,IAAM,OAAO,GAAb,MAAM,OAAO;IAClB,CAAC,aAAa,CAAC,CAAoC;IAInD,EAAE,GAAW,UAAU,EAAE,CAAC;IAE1B;mGAC+F;IAG/F,SAAS,CAAU;IAEnB,uEAAuE;IAGvE,iBAAiB,CAAiB;IAElC,+DAA+D;IAG/D,WAAW,CAAiB;IAE5B;;;OAGG;IAEH,uBAAuB,CAAiB;IAIxC,SAAS,CAAQ;IAGjB,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,UAAU,CAAe;IAGzB,SAAS,CAAiB;IAG1B,SAAS,CAAiB;CAC3B,CAAA;AA3CC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mCACH;AAM1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACzC,KAAK,EAAE;;0CACW;AAKnB;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,KAAK,EAAE;;kDAC0B;AAKlC;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,KAAK,EAAE;;4CACoB;AAO5B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;wDACH;AAIxC;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC9B,KAAK,EAAE;8BACI,IAAI;0CAAC;AAGjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;0CAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;0CAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2CACtB;AAGzB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CAC/B;AAG1B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CAChC;AA/Cf,OAAO;IAFnB,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;GACrB,OAAO,CAgDnB"}
@@ -0,0 +1,120 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { Redis } from 'ioredis';
3
+ import type { ModuleContext } from '@endora-commerce/platform/kernel';
4
+ import type { AdminPermissionChecker } from '@endora-commerce/platform/kernel';
5
+ import { Session } from './entities/session.entity.js';
6
+ import { SessionService } from './services/session-service.js';
7
+ /**
8
+ * `auth` — the module every other module's guards read (feature 072, T078).
9
+ *
10
+ * Three things about this conversion are not shared with the modules that
11
+ * follow it, and each is a property of what `auth` is rather than of how it was
12
+ * written.
13
+ *
14
+ * 1. **Its plugin goes through `ctx.rootPlugin`, not `ctx.routes`.** It
15
+ * contributes no routes; it decorates `request.actor`, which every module's
16
+ * guards read. Both routes seams encapsulate, and a decoration applied
17
+ * inside a Fastify child context is invisible to that context's siblings —
18
+ * so registering it through either would leave every module but this one
19
+ * with no actor.
20
+ * 2. **Its ports are the only ones a disabled `auth` could withdraw, and it
21
+ * cannot be disabled.** `requireAdmin` gates 205 call sites across 60
22
+ * modules; a platform whose admin guard is absent has no admin surface to
23
+ * speak of, so the manifest declares the module non-deactivatable and the
24
+ * orchestrator refuses to switch it off. The port gate is still registered
25
+ * rather than skipped: the check that can never fire costs one predicate,
26
+ * and an exception carved into the port machinery would cost a reader's
27
+ * confidence in every other gate.
28
+ * 3. **It consumes `permissionService`, which `admin_roles` owns.** The
29
+ * manifest declares that dependency (D-32); it is the edge that made `auth`
30
+ * the first module to need `check:port-dependencies` to pass.
31
+ */
32
+ /** What `auth` resolves: its own registrations, plus what it needs from elsewhere. */
33
+ export interface AuthCradle {
34
+ readonly emFactory: () => EntityManager;
35
+ readonly redis: Redis;
36
+ /** `admin_roles`' permission checker, narrowed to what the guard uses. */
37
+ readonly permissionService: AdminPermissionChecker;
38
+ readonly sessionService: SessionService;
39
+ /**
40
+ * `api_keys`' bearer-token resolver. Registered by the composition root
41
+ * **after** this module composes: `api_keys` provides the port, and the
42
+ * single-pass composition orders it by the manifest graph rather than by
43
+ * this file. It is read per request, so the ordering is invisible here.
44
+ */
45
+ readonly apiKeyResolver: ((token: string) => Promise<{
46
+ apiKeyId: string;
47
+ scopes: string[];
48
+ organizationId?: string | null;
49
+ salesChannelId?: string | null;
50
+ customerAccountId?: string | null;
51
+ } | null>) | undefined;
52
+ /** Resolves a customer account to its organisation. Same late-binding story. */
53
+ readonly customerOrgResolver: ((customerAccountId: string) => Promise<string | null>) | undefined;
54
+ }
55
+ export declare function registerModule(ctx: ModuleContext): void;
56
+ /**
57
+ * The module's persisted entity classes, on the `./backend` subpath, as one
58
+ * array and **no named class export** (D-168).
59
+ *
60
+ * This is the shape the platform reads when the package is *installed*: the
61
+ * boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
62
+ * and the static declaration reader (`scripts/lib/package-declarations.ts`),
63
+ * which is the third source of `check:module-boundary`'s `table→owner` map and
64
+ * the package pass of `check-entity-tenant-classification`. A missing array is
65
+ * answered with `[]` — zero entities registered, no error anywhere.
66
+ */
67
+ export declare const entities: (typeof Session)[];
68
+ /**
69
+ * The module's own implementation classes and guard factories, on the
70
+ * `./backend` subpath.
71
+ *
72
+ * They are published for the reason `pim_ergonode` publishes
73
+ * `ErgonodeRequestError`: a consumer that needs the **class** must get the one
74
+ * the platform composed. `SessionService` reaches `Session` and
75
+ * `AuthSessionReadService` reaches it too, so a second copy of either is a
76
+ * second `Session` — a class the ORM never discovered, and `em.find` answers a
77
+ * `MetadataError` rather than rows (D-160.6.1). Publishing them is what lets a
78
+ * consumer name one copy instead of resolving a filesystem path into this
79
+ * package's source.
80
+ *
81
+ * No module reaches any of these; the consumers today are `backend/test/`,
82
+ * which is why they are not on a `./ports` subpath — that one is contract
83
+ * surface (D-171) and these are implementations.
84
+ */
85
+ /**
86
+ * What `request.actor` **is** — and it is no longer this package's to say
87
+ * (`specs/110-instance-repository/` T118b).
88
+ *
89
+ * `plugin.ts` used to declare the four actor kinds and a
90
+ * `declare module 'fastify'` block adding `actor` and `adminActor` to
91
+ * `FastifyRequest`, and this barrel re-exported the five type names.
92
+ * `specs/117-instance-bring-up/` FR-030 published them for a real reason: an
93
+ * ambient augmentation reaches a consumer's program only if the file declaring
94
+ * it is *in* that program, and the production composition root was getting it
95
+ * incidentally through a **value** import of `promoteAdminActor`. Retiring that
96
+ * import took the augmentation with it and thirty reads of `request.actor`
97
+ * stopped compiling.
98
+ *
99
+ * The block said relocating the augmentation *"would take `Session` with it"*.
100
+ * That premise was false and is what T118b measured: across `packages/`,
101
+ * `backend/`, `admin/` and `storefront/`, `actor.session` was read in **zero**
102
+ * files outside this package. So the vocabulary is
103
+ * `@endora-commerce/contracts`' {@link Actor} — session-free, importing neither
104
+ * Fastify nor the ORM — and the augmentation is the platform's, on
105
+ * `@endora-commerce/platform/http`. A consumer names one of those two; neither
106
+ * is a boundary reach, and no consumer needs a type-only import of a module any
107
+ * more.
108
+ *
109
+ * The five names are **not** re-exported from here. A re-export of a
110
+ * `@endora-commerce/contracts` type on this package's `./backend` barrel is
111
+ * what `module-package-entity-surface.test.ts` refuses under D-168: it cannot
112
+ * follow the specifier, so whether a named entity class comes through it is
113
+ * unknown rather than false. That is the same rule that stopped this file
114
+ * re-exporting the two cookie names when the package landed.
115
+ */
116
+ export { SessionService } from './services/session-service.js';
117
+ export { AuthSessionReadService, createAuthSessionPort } from './services/session-port.js';
118
+ export { createRequireAdmin, createRequireAdminAny } from './require-admin.js';
119
+ export { createRequireCustomer } from './require-customer.js';
120
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAK/E,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,iBAAiB,EAAE,sBAAsB,CAAC;IACnD,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EACnB,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,GAAG,IAAI,CAAC,CAAC,GACV,SAAS,CAAC;IACd,gFAAgF;IAChF,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CACnG;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA0HvD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,oBAAY,CAAC;AA+BlC;;;;;;;;;;;;;;;;GAgBG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,194 @@
1
+ import { effectiveState } from '@endora-commerce/platform/kernel';
2
+ import { authPlugin, promoteAdminActor } from './plugin.js';
3
+ import { createRequireAdmin, createRequireAdminAny } from './require-admin.js';
4
+ import { createRequireCustomer } from './require-customer.js';
5
+ import { AuthSessionReadService, createAuthSessionPort } from './services/session-port.js';
6
+ import { Session } from './entities/session.entity.js';
7
+ import { SessionService } from './services/session-service.js';
8
+ export function registerModule(ctx) {
9
+ ctx.di.register({
10
+ sessionService: ctx
11
+ .asFunction(({ emFactory, redis }) => new SessionService(emFactory, redis))
12
+ .singleton(),
13
+ });
14
+ // `requireAdmin` is the platform's single admin guard and the most-resolved
15
+ // name in the tree. It is a port because it is resolved by 60 other modules;
16
+ // `requireAdminAny` is the same guard with an any-of-these-codes predicate,
17
+ // and lives here for the same reason (`promoteAdminActor` plus a permission
18
+ // check are both this module's business).
19
+ //
20
+ // Both guards read `permissionService` **per check**, not at construction,
21
+ // and that is a correctness requirement rather than a style choice.
22
+ // `permissionService` is a port owned by `admin_roles`, so its resolution is
23
+ // gated on that module's effective state; a guard that captured the instance
24
+ // once would keep answering from it after the module went away, which is the
25
+ // permissive failure the gate exists to prevent. Awilix enforces the same
26
+ // thing from the other side — a singleton may not depend on the transient
27
+ // gate wrapper — so the two agree.
28
+ const permissionChecker = () => ({
29
+ hasPermission: (adminUserId, permission) => ctx.cradle().permissionService.hasPermission(adminUserId, permission),
30
+ });
31
+ // Feature 075 Phase P — the published session surface. `sessionService` keeps
32
+ // its registration for the four modules Phase C has not rewired yet; these two
33
+ // are what they rewire *to*, and the difference is that neither hands a
34
+ // `Session` entity across the boundary.
35
+ //
36
+ // `providePort` rather than `register`, even though `auth` is
37
+ // non-deactivatable and the gate can therefore never close: this module made
38
+ // that call already for `requireAdmin` (see the note above), and a second
39
+ // answer inside one module would be worse than either answer.
40
+ ctx.di.providePort('authSessionPort', ctx
41
+ .asFunction(({ sessionService }) => createAuthSessionPort(sessionService))
42
+ .singleton());
43
+ ctx.di.providePort('authSessionReadPort', ctx.asFunction(({ emFactory }) => new AuthSessionReadService(emFactory)).singleton());
44
+ ctx.di.providePort('requireAdmin', ctx.asFunction(() => createRequireAdmin({ permissionService: permissionChecker() })).singleton());
45
+ ctx.di.providePort('requireAdminAny', ctx
46
+ .asFunction(() => createRequireAdminAny({ permissionService: permissionChecker() }))
47
+ .singleton());
48
+ // The promotion the two admin guards above already perform, published under
49
+ // its own name (`specs/117-instance-bring-up/` FR-030). It is not a third
50
+ // guard: it decides nothing and refuses nobody, it moves `request.adminActor`
51
+ // into `request.actor` so that an admin route works on a request that also
52
+ // carries a customer session.
53
+ //
54
+ // It is a port for one consumer — the production composition root, which
55
+ // calls it inside the actor bridge it contributes to `mfa`. That root is
56
+ // moving into `@endora-commerce/platform` (`specs/110-instance-repository/`
57
+ // T118), and a platform file may not import a module (D-52, D-53), so the
58
+ // function's *exported* spelling stops being available to it while the
59
+ // container name survives the move. This is the drain condition the barrel
60
+ // below and `test/contract/kernel/harness-parity.test.ts` both named.
61
+ //
62
+ // `providePort` like its four neighbours, on the same reasoning: the gate can
63
+ // never close, because `auth` is non-deactivatable, and a second answer
64
+ // inside one module would be worse than either answer. No type argument, for
65
+ // symmetry with the two guards above — the shape is
66
+ // `AdminActorPromotion` in the platform's `kernel/ports/require-admin.ts`,
67
+ // deliberately off the `./kernel` barrel because no module resolves it.
68
+ ctx.di.providePort('promoteAdminActor', ctx.asFunction(() => promoteAdminActor).singleton());
69
+ // The customer-side twin, and the last guard either composition root still
70
+ // declared for itself (issue #43). Both roots had one — reading different
71
+ // request properties and disagreeing on every request shape — while 16 route
72
+ // surfaces took production's and 11 the harness's. It reads nothing but the
73
+ // actor, so unlike the two above it closes over no collaborator.
74
+ ctx.di.providePort('requireCustomer', ctx.asFunction(() => createRequireCustomer()).singleton());
75
+ ctx.rootPlugin('decorates request.actor and request.adminActor, which every module’s route ' +
76
+ 'guards read — a decoration applied inside an encapsulated context would ' +
77
+ 'reach none of them', async (app) => {
78
+ const cradle = ctx.cradle();
79
+ await app.register(authPlugin, {
80
+ sessionService: cradle.sessionService,
81
+ // Read per request, so a resolver the root registers after this module
82
+ // composed is still found. Passing the cradle read rather than the
83
+ // value is what makes the late binding work without a mutable holder.
84
+ //
85
+ // The presence probe is D-44's `degrades-without` guard, and the `?.`
86
+ // beside it does **not** replace it: optional chaining defends against
87
+ // "nobody registered this name", while `apiKeyResolver` is a gated port
88
+ // and a closed gate throws. Without the probe an operator switching
89
+ // `api_keys` off would turn every API-key request into a 503 from the
90
+ // request hook instead of the declared degradation, which is that such
91
+ // a request is simply not authenticated — the same answer a request
92
+ // presenting no key at all gets.
93
+ apiKeyResolver: async (token) => {
94
+ if (!effectiveState.isPresent('api_keys'))
95
+ return null;
96
+ return (await cradle.apiKeyResolver?.(token)) ?? null;
97
+ },
98
+ customerOrgResolver: async (customerAccountId) => (await cradle.customerOrgResolver?.(customerAccountId)) ?? null,
99
+ });
100
+ });
101
+ }
102
+ /**
103
+ * The module's persisted entity classes, on the `./backend` subpath, as one
104
+ * array and **no named class export** (D-168).
105
+ *
106
+ * This is the shape the platform reads when the package is *installed*: the
107
+ * boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
108
+ * and the static declaration reader (`scripts/lib/package-declarations.ts`),
109
+ * which is the third source of `check:module-boundary`'s `table→owner` map and
110
+ * the package pass of `check-entity-tenant-classification`. A missing array is
111
+ * answered with `[]` — zero entities registered, no error anywhere.
112
+ */
113
+ export const entities = [Session];
114
+ /*
115
+ * **Actor promotion is no longer on this subpath**, and the deletion is the
116
+ * point rather than a tidy-up (`specs/117-instance-bring-up/` FR-030).
117
+ *
118
+ * `promoteAdminActor` was exported here for exactly one consumer, the
119
+ * production composition root, which calls it inside the actor bridge it
120
+ * contributes to `mfa`. The export said in its own words that it was published
121
+ * *"rather than relocated"* — correctly, because `auth` reads the function
122
+ * itself from `require-admin.ts` and promotion is about `request.actor` and
123
+ * `request.adminActor`, two decorations this module owns; `absolutizePublicUrl`
124
+ * could move to the platform (T040b, criterion 8) precisely because it had no
125
+ * consumer inside `email` and this one does. That reasoning is unchanged.
126
+ *
127
+ * What changed is the consumer. `specs/110-instance-repository/` T118 moves
128
+ * that root into `@endora-commerce/platform`, where importing a module is
129
+ * D-52/D-53's refusal — so the root's spelling had to stop being an import, and
130
+ * a value import does not retire by moving a type. It resolves the container
131
+ * name `promoteAdminActor` instead, which is the **further step** the old block
132
+ * here recorded as open and which `test/contract/kernel/harness-parity.test.ts`
133
+ * named as its drain condition: *"actor promotion published as a port, resolved
134
+ * from the container"*.
135
+ *
136
+ * The export is removed rather than left beside the registration, because two
137
+ * spellings of one seam is how a root comes to take the one that does not
138
+ * survive the move — and this file is where a future author would look for
139
+ * permission. The registration is above, in `registerModule`; the shape is
140
+ * `AdminActorPromotion` in the platform's `kernel/ports/require-admin.ts`.
141
+ */
142
+ /**
143
+ * The module's own implementation classes and guard factories, on the
144
+ * `./backend` subpath.
145
+ *
146
+ * They are published for the reason `pim_ergonode` publishes
147
+ * `ErgonodeRequestError`: a consumer that needs the **class** must get the one
148
+ * the platform composed. `SessionService` reaches `Session` and
149
+ * `AuthSessionReadService` reaches it too, so a second copy of either is a
150
+ * second `Session` — a class the ORM never discovered, and `em.find` answers a
151
+ * `MetadataError` rather than rows (D-160.6.1). Publishing them is what lets a
152
+ * consumer name one copy instead of resolving a filesystem path into this
153
+ * package's source.
154
+ *
155
+ * No module reaches any of these; the consumers today are `backend/test/`,
156
+ * which is why they are not on a `./ports` subpath — that one is contract
157
+ * surface (D-171) and these are implementations.
158
+ */
159
+ /**
160
+ * What `request.actor` **is** — and it is no longer this package's to say
161
+ * (`specs/110-instance-repository/` T118b).
162
+ *
163
+ * `plugin.ts` used to declare the four actor kinds and a
164
+ * `declare module 'fastify'` block adding `actor` and `adminActor` to
165
+ * `FastifyRequest`, and this barrel re-exported the five type names.
166
+ * `specs/117-instance-bring-up/` FR-030 published them for a real reason: an
167
+ * ambient augmentation reaches a consumer's program only if the file declaring
168
+ * it is *in* that program, and the production composition root was getting it
169
+ * incidentally through a **value** import of `promoteAdminActor`. Retiring that
170
+ * import took the augmentation with it and thirty reads of `request.actor`
171
+ * stopped compiling.
172
+ *
173
+ * The block said relocating the augmentation *"would take `Session` with it"*.
174
+ * That premise was false and is what T118b measured: across `packages/`,
175
+ * `backend/`, `admin/` and `storefront/`, `actor.session` was read in **zero**
176
+ * files outside this package. So the vocabulary is
177
+ * `@endora-commerce/contracts`' {@link Actor} — session-free, importing neither
178
+ * Fastify nor the ORM — and the augmentation is the platform's, on
179
+ * `@endora-commerce/platform/http`. A consumer names one of those two; neither
180
+ * is a boundary reach, and no consumer needs a type-only import of a module any
181
+ * more.
182
+ *
183
+ * The five names are **not** re-exported from here. A re-export of a
184
+ * `@endora-commerce/contracts` type on this package's `./backend` barrel is
185
+ * what `module-package-entity-surface.test.ts` refuses under D-168: it cannot
186
+ * follow the specifier, so whether a named entity class comes through it is
187
+ * unknown rather than false. That is the same rule that stopped this file
188
+ * re-exporting the two cookie names when the package landed.
189
+ */
190
+ export { SessionService } from './services/session-service.js';
191
+ export { AuthSessionReadService, createAuthSessionPort } from './services/session-port.js';
192
+ export { createRequireAdmin, createRequireAdminAny } from './require-admin.js';
193
+ export { createRequireCustomer } from './require-customer.js';
194
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { FastifyInstance, FastifyRequest } from 'fastify';
2
+ import '@endora-commerce/platform/http';
3
+ import type { SessionService } from './services/session-service.js';
4
+ /**
5
+ * Authentication plugin. Resolves the caller's identity into one of four forms and
6
+ * exposes pre-handler factories that gate routes.
7
+ *
8
+ * See research.md R-11, R-12 and contracts/README.md § Authentication.
9
+ */
10
+ export interface AuthPluginOptions {
11
+ sessionService: SessionService;
12
+ /** Resolves an API key bearer token to an ApiKey actor. Installed by the api_keys module. */
13
+ apiKeyResolver?: (token: string) => Promise<{
14
+ apiKeyId: string;
15
+ scopes: string[];
16
+ organizationId?: string | null;
17
+ salesChannelId?: string | null;
18
+ customerAccountId?: string | null;
19
+ } | null>;
20
+ /**
21
+ * Resolves a customerAccountId to the customer's `organizationId`. Used to
22
+ * stamp `actor.organizationId` for customer + impersonation sessions so
23
+ * route handlers don't have to re-fetch the CustomerAccount per request.
24
+ */
25
+ customerOrgResolver?: (customerAccountId: string) => Promise<string | null>;
26
+ /** Cookie name used to carry customer (storefront) sessions. */
27
+ cookieName?: string;
28
+ /** Cookie name used to carry admin (Admin UI) sessions. */
29
+ adminCookieName?: string;
30
+ }
31
+ /**
32
+ * If the request carries a valid admin session (resolved into `request.adminActor`
33
+ * by the auth plugin) but its ambient `request.actor` is not already an admin,
34
+ * promote the admin candidate. Admin guards call this so an admin route works
35
+ * even when a customer session is simultaneously present on the same request.
36
+ */
37
+ export declare function promoteAdminActor(request: FastifyRequest): void;
38
+ declare function authPluginImpl(app: FastifyInstance, opts: AuthPluginOptions): Promise<void>;
39
+ export declare const authPlugin: typeof authPluginImpl;
40
+ export {};
41
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/backend/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAa/D,OAAO,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE;;;;;GAKG;AAuBH,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,6FAA6F;IAC7F,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;QAC1C,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC,GAAG,IAAI,CAAC,CAAC;IACV;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5E,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAoBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAK/D;AAED,iBAAe,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuH1F;AAED,eAAO,MAAM,UAAU,uBAGrB,CAAC"}