create-astram-app 0.4.0 → 0.6.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 (87) hide show
  1. package/README.md +211 -38
  2. package/dist/add-frontend.js.map +1 -1
  3. package/dist/index.js +14 -9
  4. package/dist/index.js.map +1 -1
  5. package/package.json +2 -2
  6. package/template/README.md +51 -20
  7. package/template/frontend/README.md +21 -11
  8. package/template/frontend/index.html +16 -0
  9. package/template/frontend/package.json +1 -1
  10. package/template/frontend/src/App.jsx +95 -20
  11. package/template/frontend/src/auth/AuthContext.jsx +145 -21
  12. package/template/frontend/src/auth/routeGate.js +31 -0
  13. package/template/frontend/src/auth/routeGate.test.mjs +59 -0
  14. package/template/frontend/src/auth/sessionFlow.js +27 -0
  15. package/template/frontend/src/auth/sessionFlow.test.mjs +63 -0
  16. package/template/frontend/src/components/EntityList.jsx +1 -7
  17. package/template/frontend/src/components/MultiSelectChecklist.jsx +166 -0
  18. package/template/frontend/src/components/PageHeader.jsx +5 -4
  19. package/template/frontend/src/components/ShareDialog.jsx +3 -5
  20. package/template/frontend/src/components/access/CollapsibleGroup.jsx +4 -1
  21. package/template/frontend/src/components/ui/alert-dialog.tsx +27 -50
  22. package/template/frontend/src/components/ui/alert.tsx +17 -23
  23. package/template/frontend/src/components/ui/avatar.tsx +8 -20
  24. package/template/frontend/src/components/ui/badge.tsx +17 -26
  25. package/template/frontend/src/components/ui/button.tsx +22 -24
  26. package/template/frontend/src/components/ui/card.tsx +19 -36
  27. package/template/frontend/src/components/ui/checkbox.tsx +7 -10
  28. package/template/frontend/src/components/ui/date-field.tsx +26 -27
  29. package/template/frontend/src/components/ui/dialog.tsx +24 -40
  30. package/template/frontend/src/components/ui/dropdown-menu.tsx +25 -54
  31. package/template/frontend/src/components/ui/input-otp.tsx +1 -4
  32. package/template/frontend/src/components/ui/label.tsx +10 -12
  33. package/template/frontend/src/components/ui/searchable-select.tsx +1 -3
  34. package/template/frontend/src/components/ui/select.tsx +31 -43
  35. package/template/frontend/src/components/ui/separator.tsx +6 -6
  36. package/template/frontend/src/components/ui/sheet.tsx +29 -38
  37. package/template/frontend/src/components/ui/skeleton.tsx +3 -3
  38. package/template/frontend/src/components/ui/sonner.tsx +7 -7
  39. package/template/frontend/src/components/ui/table.tsx +56 -70
  40. package/template/frontend/src/components/ui/tooltip.tsx +7 -11
  41. package/template/frontend/src/config/branding.js +1 -4
  42. package/template/frontend/src/hooks/useMobile.tsx +4 -6
  43. package/template/frontend/src/index.css +9 -4
  44. package/template/frontend/src/pages/Dashboard.jsx +13 -7
  45. package/template/frontend/src/pages/ForgotPassword.jsx +9 -2
  46. package/template/frontend/src/pages/Login.jsx +85 -70
  47. package/template/frontend/src/pages/ResetPassword.jsx +9 -2
  48. package/template/frontend/src/pages/access/AccessForm.jsx +49 -15
  49. package/template/frontend/src/pages/access/AccessPage.jsx +10 -6
  50. package/template/frontend/src/pages/access/RecordPoliciesPage.jsx +9 -2
  51. package/template/frontend/src/pages/account/AccountLayout.jsx +11 -6
  52. package/template/frontend/src/pages/account/ChangePasswordPage.jsx +2 -2
  53. package/template/frontend/src/pages/account/ReenrollPage.jsx +3 -5
  54. package/template/frontend/src/pages/account/TwoFactorPage.jsx +3 -8
  55. package/template/frontend/src/pages/companies/CompaniesPage.jsx +7 -9
  56. package/template/frontend/src/pages/cross-tenant/GrantForm.jsx +41 -8
  57. package/template/frontend/src/pages/cross-tenant/GrantsPage.jsx +30 -7
  58. package/template/frontend/src/pages/cross-tenant/InboxPage.jsx +12 -3
  59. package/template/frontend/src/pages/roles/RolesPage.jsx +5 -9
  60. package/template/frontend/src/pages/service-accounts/KeyRevealDialog.jsx +104 -0
  61. package/template/frontend/src/pages/service-accounts/ServiceAccountAccessDialog.jsx +231 -0
  62. package/template/frontend/src/pages/service-accounts/ServiceAccountActionsMenu.jsx +56 -0
  63. package/template/frontend/src/pages/service-accounts/ServiceAccountsPage.jsx +368 -0
  64. package/template/frontend/src/pages/service-accounts/accessModel.js +158 -0
  65. package/template/frontend/src/pages/service-accounts/accessModel.test.mjs +189 -0
  66. package/template/frontend/src/pages/users/MembershipCard.jsx +3 -1
  67. package/template/frontend/src/pages/users/PostingRow.jsx +8 -14
  68. package/template/frontend/src/pages/users/UsersPage.jsx +7 -9
  69. package/template/frontend/src/platform/httpClient.js +5 -0
  70. package/template/frontend/src/platform/sessionStore.js +55 -13
  71. package/template/frontend/src/platform/sessionStore.test.mjs +89 -0
  72. package/template/frontend/src/platform/shieldTransport.js +6 -0
  73. package/template/frontend/src/platform/shieldTransport.test.mjs +84 -5
  74. package/template/frontend/src/shell/AppShell.jsx +10 -12
  75. package/template/frontend/src/shell/Sidebar.jsx +15 -3
  76. package/template/frontend/src/shell/nav.js +13 -3
  77. package/template/frontend/vite.config.js +19 -1
  78. package/template/server/_env.example +22 -1
  79. package/template/server/eslint.config.mjs +194 -0
  80. package/template/server/package.json +11 -11
  81. package/template/server/scripts/dev.mjs +17 -6
  82. package/template/server/scripts/sync-astram-guide.mjs +45 -19
  83. package/template/server/src/app.module.ts +11 -5
  84. package/template/server/src/health/demo.controller.ts +16 -12
  85. package/template/server/src/main.ts +23 -1
  86. package/template/server/test/enforcement.e2e.spec.ts +73 -6
  87. package/template/server/eslint.config.js +0 -95
package/README.md CHANGED
@@ -1,61 +1,234 @@
1
1
  # create-astram-app
2
2
 
3
- The Astram app scaffolder (ADR-0023 §3). Emits a **new consumer app** that depends
4
- on the published, immutable framework (`@astram/core`, `@astram/guard`,
5
- `@astram/sdk`) and enforces **deny-by-default** from the first boot.
3
+ The Astram app scaffolder (ADR-0023 §3). It emits a **new consumer app**: a NestJS API that
4
+ depends on the published, immutable framework packages and enforces **deny-by-default** from the
5
+ first boot, plus (optionally) a complete identity frontend. You write features; the framework
6
+ owns identity, authentication, sessions, authorization and audit.
6
7
 
7
8
  ## Use it
8
9
 
9
10
  ```bash
10
- npx create-astram-app my-app
11
- cd my-app
11
+ npx create-astram-app my-app # server/ only
12
+ npx create-astram-app my-app --with-frontend # server/ + frontend/ (identity UI)
13
+ ```
14
+
15
+ `--with-frontend` may come before or after the name. The app name must be a single directory
16
+ name (letters, numbers, `.`, `_`, `-`; no leading dot).
17
+
18
+ ```bash
19
+ cd my-app/server
12
20
  npm install
13
- npm run dev # boots the app; GET /health → 200, unclassified route → 403
21
+ npm run dev # API on http://localhost:3000; GET /health → 200, GET /demo/public → 200
22
+ npm test # proves deny-by-default (an unclassified route is denied)
23
+
24
+ cd ../frontend # only with --with-frontend
25
+ npm install
26
+ npm run dev # identity UI on http://localhost:5173 (proxies /api → :3000)
14
27
  ```
15
28
 
16
- ## What it emits
29
+ ### Add the frontend to an existing app
30
+
31
+ ```bash
32
+ cd my-app # the app root (the folder that holds server/)
33
+ npx -p create-astram-app astram-add-frontend
34
+ ```
17
35
 
18
- A running, framework-**enforced** NestJS app (the minimal, clean version of
19
- [`examples/example-backend/`](../examples/example-backend/)):
36
+ `astram-add-frontend` is a second bin in the `create-astram-app` package, so `npx` needs
37
+ `-p create-astram-app` unless the package is already installed (then plain
38
+ `npx astram-add-frontend` works). It copies the frontend template into `./frontend/`, substitutes
39
+ the app name from `./package.json` (or the folder name), and **never overwrites an existing
40
+ file**. Re-running it later only adds files the newer template has and your copy lacks.
41
+
42
+ ## What it emits
20
43
 
21
44
  ```
22
45
  my-app/
23
- ├── package.json depends on @astram/core ^0.1.0, @astram/guard ^0.1.1,
24
- │ @astram/sdk ^0.1.0 (published ranges — NEVER workspace:*),
25
- │ plus the NestJS runtime. "private": true.
26
- ├── tsconfig.json + tsconfig.build.json
27
- ├── vitest.config.ts
28
- ├── src/
29
- │ ├── main.ts bootstraps Nest; loadAppConfig from @astram/guard
30
- │ ├── app.module.ts imports ShieldModule.forRoot() — the ONE seam
31
- │ ├── health/ @Public health probes + a demo denied route (enforcement proof)
32
- │ └── features/ EMPTY — the developer's editable space
33
- ├── test/ enforcement e2e (200 health + 403 unclassified)
34
- ├── .astram/guide/ DEVELOPER-OWNED guide layer (ADR-0025) — upgrade-safe, never touched
35
- ├── .env.example config references only (safe defaults; boots with no .env)
36
- ├── .gitignore
37
- └── README.md how to run + how to add features the framework way
46
+ ├── server/ the API (NestJS) — always emitted
47
+ │ ├── package.json @astram/core, guard, engine, identity, migrate, guide, sdk as
48
+ │ │ published semver ranges (never workspace:*), NestJS runtime
49
+ │ ├── src/main.ts bootstrap; reads TRUST_PROXY → Express `trust proxy`
50
+ │ ├── src/app.module.ts ShieldModule.forRoot() — the ONE seam (auth/identity wiring
51
+ │ │ documented in its header comment)
52
+ │ ├── src/health/ @Public health probes + /demo/public (the unclassified demo
53
+ │ │ route is commented out → 404; see demo.controller.ts)
54
+ │ ├── src/features/ EMPTY — your editable space
55
+ │ ├── test/ enforcement e2e: 200 health; a test-only unclassified route is
56
+ │ │ denied 403 and fails the verifyGatable boot check
57
+ │ ├── eslint.config.mjs the feature wall: no raw DB access anywhere in src/** except
58
+ │ │ app.module.ts / main.ts
59
+ │ ├── scripts/ dev runner (sets NODE_ENV=development), guide sync
60
+ │ └── .env.example config references only (boots with no .env)
61
+ ├── frontend/ only with --with-frontend (see below)
62
+ ├── .astram/guide/ DEVELOPER-OWNED guide layer (ADR-0025) — never touched on upgrade
63
+ ├── CLAUDE.md, .gitignore
64
+ └── README.md how to run + how to add features the framework way
65
+ ```
66
+
67
+ `server/` scripts: `dev`, `build`, `start`, `test`, `lint`, `migration:run`,
68
+ `migration:status`, `migration:revert`, `guide:sync`.
69
+
70
+ ## The frontend (`--with-frontend` / `astram-add-frontend`)
71
+
72
+ A Vite + React + shadcn/ui app whose views you own and edit; the auth and API logic comes from
73
+ `@astram/frontend-core` and `@astram/sdk` and updates with `npm update`. See
74
+ `frontend/FRONTEND.md` in the generated app for the update and re-skin model.
75
+
76
+ - **Sign-in flows:** login, MFA challenge (TOTP or a recovery code), forced MFA re-enrolment
77
+ after a recovery-code login, forgot password, reset password.
78
+ - **Account:** profile, change password, two-factor devices and recovery codes.
79
+ - **Administration** (shown only to users whose roles grant it): companies, users (memberships
80
+ and role postings), roles, access (role grants and access bundles), record policies (guided rule
81
+ builder), service accounts (roles, scope, API keys with an explicit expiry), cross-tenant grants
82
+ (offer, inbox, revoke), audit log; owner shares from record screens.
83
+ - **Sessions:** a 401 refreshes the access token once and retries (single-flight, shared across
84
+ tabs with Web Locks); a refresh outage keeps you signed in; a rejected refresh signs you out and
85
+ remembers the page; sign-out in one tab reaches the others.
86
+ - **Content-Security-Policy:** `index.html` ships a strict CSP (`script-src 'self'`, no inline
87
+ script or eval). A dev-only Vite plugin relaxes it for hot reload. If your API is not served
88
+ same-origin under `/api`, add its origin to `connect-src`.
89
+
90
+ The admin pages need the server's identity wiring (below); without it they 404.
91
+
92
+ ## Turning on auth and the identity admin
93
+
94
+ `server/src/app.module.ts` starts enforcement-only (`ShieldModule.forRoot()`: no database, no
95
+ Redis). Its header comment shows the full wiring. In short:
96
+
97
+ ```ts
98
+ const rootIds: string[] = [/* platform-admin user uuids, read from your config */];
99
+ const authzPool = createIdentityAuthzPool(); // from @astram/identity
100
+
101
+ imports: [
102
+ ShieldModule.forRoot({
103
+ auth: true,
104
+ emailSender: myEmailSender, // or 'disabled'
105
+ rootIds,
106
+ identityActionKeys: identityAuthActionKeys,
107
+ identityControlPlaneKeys,
108
+ recordAuthorization: buildIdentityRecordAuthorization(authzPool, [/* YourType */]),
109
+ }),
110
+ IdentityFeatureModule.forRoot({ rootIds, extraObjects: [/* YourType */] }),
111
+ ],
38
112
  ```
39
113
 
114
+ ## Production requirements
115
+
116
+ With `auth: true`, check every item before the first production deploy.
117
+
118
+ - **`emailSender`.** Outside `NODE_ENV=development|test`, `auth: true` fails boot unless you pass
119
+ an `EmailSender` (`send({ to, subject, html, text })`, e.g. SMTP or SendGrid) or
120
+ `emailSender: 'disabled'` (no reset emails; `POST /auth/forgot-password` still answers 204).
121
+ The dev logger, which prints reset links, is never used in production.
122
+ - **Explicit `NODE_ENV`.** Set `NODE_ENV=production`. `npm run dev` sets `development` for you;
123
+ `npm start` sets nothing. An unset `NODE_ENV` counts as production for the email rule, and the
124
+ framework's dev seed migrations run only under `development` (or `ASTRAM_SEED_DEV=1`).
125
+ - **`TRUST_PROXY`.** The real number of reverse-proxy hops in front of the app (`0` = none,
126
+ `1` = behind the Astram Traefik). Unset turns the per-IP limits for login, forgot-password and
127
+ reset-password off, with a boot warning. Too high lets clients spoof their IP.
128
+ - **`REFRESH_HMAC_KEY`.** A long random secret, supplied through your secrets mechanism, never
129
+ committed. Boot fails without it.
130
+ - **Redis.** Required with auth: sessions, cached permission facts, the permission version, MFA
131
+ challenges and rate limits live there, and the request path reads only Redis. If Redis is down,
132
+ requests fail closed (401) and refresh answers 503, within `REDIS_COMMAND_TIMEOUT_MS` (default
133
+ 2000). The app's Redis user must be allowed `EVAL` (the shipped `infra/redis` ACL allows it;
134
+ check your production ACL).
135
+ - **`rootIds`.** Pass the same platform-administrator user uuids to `ShieldModule.forRoot` and
136
+ `IdentityFeatureModule.forRoot`, from config. Without them nobody logs in as root and the
137
+ identity module logs a boot warning. The generated `app.module.ts` does not pass them yet; add
138
+ them when you turn auth on.
139
+ - **Migrations with the DDL account.** Run `npm run migration:run` with `DDL_DB_USER` /
140
+ `DDL_DB_PASSWORD` (a DDL-capable deploy account; host, port and database come from `APP_DB_*`).
141
+ The running app's `APP_DB_*` account must not hold DDL. The framework's guard and identity
142
+ migrations run first, then yours (`APP_MIGRATION_DIR`). Upgrading to guard 0.8 needs identity
143
+ migration `1710000000019-AddSessionMustReenroll`: apply migrations **before** starting the new
144
+ version. Concurrent deploys are safe (migrations hold a database lock;
145
+ `APP_MIGRATION_LOCK_TIMEOUT`, default 120 s).
146
+ - **`--strict`.** `migration:status` and `migration:run` report migrations whose file changed
147
+ after they ran (drift). Add `--strict` in CI against a fresh database to fail on drift. Do not
148
+ edit an applied migration. Out-of-order pending migrations are only a warning, because
149
+ framework upgrades ship migrations older than your own.
150
+ - **Existing Astram infra database volumes.** Init SQL runs only on an empty volume. On a volume
151
+ created before 2026-10-08, apply
152
+ `infra/mariadb/upgrade/2026-10-08-shield-core-audit-append-only.sql` once as root (it makes the
153
+ runtime `shield_core` account append-only on `shield_audit`). See `infra/README.md` in the
154
+ astram-framework repo.
155
+ - **API clients other than the generated frontend** must refresh tokens one at a time (one
156
+ in-flight `/auth/refresh` per session). Concurrent refreshes of the same token can trip reuse
157
+ detection, which revokes the session (the user must sign in again).
158
+
159
+ ## Upgrading from 0.5.x
160
+
161
+ The generated app owns its files, and the scaffolder never overwrites them, so an upgrade has
162
+ two parts.
163
+
164
+ **1. Bump the framework ranges** in `server/package.json` (`@astram/core` ^1.4.0,
165
+ `@astram/guard` ^0.8.0, `@astram/engine` ^0.4.0, `@astram/identity` ^0.5.0,
166
+ `@astram/migrate` ^0.3.0, `@astram/guide` ^0.2.0; `@nestjs/*` ^11.2.7) and
167
+ `frontend/package.json` (`@astram/frontend-core` ^0.5.0), then `npm install` in both. Run the
168
+ migrations before starting the new server.
169
+
170
+ **2. Copy these files from a fresh scaffold** (`npx create-astram-app@latest tmp-app
171
+ --with-frontend`), and merge by hand where you changed them:
172
+
173
+ | File | Why |
174
+ |---|---|
175
+ | `server/src/main.ts` | reads `TRUST_PROXY` |
176
+ | `server/scripts/dev.mjs` | `npm run dev` sets `NODE_ENV=development` |
177
+ | `server/eslint.config.mjs` (delete the old `eslint.config.js`), `lint` script in `server/package.json` | lint no longer crashes; wider feature wall over `src/**/*.{ts,mts,cts}` |
178
+ | `server/scripts/sync-astram-guide.mjs` | guide sync only in an app root, `ASTRAM_GUIDE_SYNC=0`, never fails install |
179
+ | `server/.env.example` | `TRUST_PROXY`, `NODE_ENV`, `REDIS_COMMAND_TIMEOUT_MS`, `LOGIN_IP_*` |
180
+ | `frontend/src/auth/AuthContext.jsx`, `sessionFlow.js`, `routeGate.js` | token refresh; admin nav after a fresh login; gated deep links |
181
+ | `frontend/src/App.jsx` | `RequireAuth` waits for auth facts |
182
+ | `frontend/src/platform/sessionStore.js` (plus doc-only `httpClient.js`, `shieldTransport.js`) | cross-tab session sync |
183
+ | `frontend/index.html`, `frontend/vite.config.js` | Content-Security-Policy and its dev relaxation |
184
+ | `frontend/src/pages/service-accounts/ServiceAccountsPage.jsx`, `accessModel.js` | asks for an API-key expiry (the server now requires one) |
185
+
186
+ **Breaking and behaviour changes** (details in each package's CHANGELOG):
187
+
188
+ - **guard 0.8 (breaking):** `auth: true` outside development/test fails boot without
189
+ `emailSender` (or `'disabled'`).
190
+ - **Login:** users with a confirmed MFA device must complete `/auth/mfa` on every password login;
191
+ 5 wrong TOTP codes lock MFA for 15 minutes; a TOTP code works once. Lockout counters are per
192
+ account now (they reset once on upgrade). Per-IP limits need `TRUST_PROXY`. Disabled accounts
193
+ cannot sign in, and disabling a user ends their sessions.
194
+ - **Sessions:** a refresh-minted access token lives at most the access TTL; the previous token
195
+ stops working 30 s after a refresh; a replayed refresh token kills the session's live access
196
+ tokens; roles follow posting changes on the next request without re-login; after a Redis loss
197
+ the next refresh rebuilds the session instead of forcing a login. A Redis outage now fails fast
198
+ (about 2 s) instead of hanging; rate limiters stop limiting during the outage.
199
+ - **Identity API:** errors map to 403/404/409/400/503 instead of 500. `PUT /identity/companies/:uuid`
200
+ changes only `name`/`status`; moves use `PUT /identity/companies/:uuid/parent`. User updates
201
+ accept only `username`/`email`/`status`, and changing another user's email or status needs
202
+ dominance over that user. Role grants and postings are limited to roles you hold and that are
203
+ used only inside your subtree. Non-root admins cannot create top-level companies or attach a
204
+ user from outside their subtree. Grant changes are audited. Issuing a service-account key needs
205
+ `expiresAtMs` or `neverExpires: true`. API keys use the account's current scope and roles.
206
+ - **Engine:** non-root creates of subtree-scoped types are walled (403 outside your subtree);
207
+ update/delete/get of an unreachable id is a 403 instead of a silent no-op; record rules with
208
+ field conditions now apply to single-record reads and writes; unsorted lists come back in
209
+ primary-key order. Custom `RecordEngine` implementations must add `transaction` and
210
+ `lockForUpdate`.
211
+ - **Migrate:** migrations are ordered numerically (mixed-width prefixes may reorder; check
212
+ `migration:status`), runs take a database lock, and the tracking table gains a `checksum` column
213
+ (added automatically).
214
+ - **Core:** registering the same `(typeKey, actionKey)` twice across modules now fails at boot.
215
+
40
216
  ## Guarantees
41
217
 
42
- - **Immutable-core consumption** — the emitted `package.json` uses published semver
43
- ranges, never `workspace:*` and never a source symlink. The framework upgrades via
44
- `npm update`; the app's `src/` is never touched.
45
- - **Never clobbers** — scaffolding into an existing directory only writes files that
46
- do NOT already exist. A developer-authored `docs/`, `.astram/guide/`, `README`, or
47
- any other file is left exactly as-is (and reported as skipped). astram3's program
48
- docs survive scaffolding.
49
- - **Runs immediately** — `npm install && npm run dev` boots a framework-enforced app
50
- with no further wiring. (A turnkey login/session boilerplate arrives in a later
51
- framework release; today the app gives correct-by-default enforcement.)
52
- - **Honest** — the CLI never prints "not implemented"; it scaffolds a real app and
53
- tells you how to run it and add a feature.
218
+ - **Immutable-core consumption** — the emitted `package.json` files use published semver ranges,
219
+ never `workspace:*` or a source symlink. The framework upgrades via `npm update`; your `src/`
220
+ is never touched.
221
+ - **Never clobbers** — scaffolding into an existing directory (or re-running
222
+ `astram-add-frontend`) writes only files that do not exist yet. Your `docs/`, `.astram/guide/`,
223
+ README and edited files are left as they are and reported as skipped.
224
+ - **Runs immediately** — `npm install && npm run dev` boots a framework-enforced API with no
225
+ `.env`. Real login and the identity admin need the database, Redis and the wiring above.
54
226
 
55
227
  ## Commands (for developing this package)
56
228
 
57
229
  ```bash
58
- pnpm --filter create-astram-app build # tsc → dist/index.js (the CLI)
59
- pnpm --filter create-astram-app test # vitest — CLI + never-clobber + emitted-shape
230
+ pnpm --filter create-astram-app build # tsc → dist/index.js, dist/add-frontend.js
231
+ pnpm --filter create-astram-app test # vitest — CLI, never-clobber, emitted shape, lint wall
60
232
  pnpm --filter create-astram-app lint
233
+ pnpm template:verify # (repo root) scaffold + build/lint/test against packed tarballs
61
234
  ```
@@ -1 +1 @@
1
- {"version":3,"file":"add-frontend.js","sourceRoot":"","sources":["../src/add-frontend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"add-frontend.js","sourceRoot":"","sources":["../src/add-frontend.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -11,17 +11,18 @@
11
11
  * builds features in the emitted `src/features/`; the framework lives read-only
12
12
  * in `node_modules` and upgrades through `npm update`.
13
13
  *
14
- * What the emitted app IS today (honest scope — Phase 0a):
14
+ * What the emitted app IS:
15
15
  * A running, framework-ENFORCED NestJS app. `ShieldModule.forRoot()` is the ONE
16
16
  * registration seam: it wires the global deny-by-default guard (ADR-0002), so
17
17
  * every route is denied unless explicitly classified (`@Public()`/`@Classified()`).
18
18
  * Health probes + a demo route prove enforcement from the consumer's side.
19
- * A turnkey login/session boilerplate arrives in a later framework release — this
20
- * scaffold does NOT emit a fake login route.
19
+ * Login, sessions, MFA and the identity admin come from the framework: turn them on
20
+ * with `ShieldModule.forRoot({ auth: true, … })` + `IdentityFeatureModule.forRoot()` (see
21
+ * the comment block in server/src/app.module.ts). `--with-frontend` adds the web UI.
21
22
  *
22
23
  * Reference skeleton: `examples/example-backend/` in the astram-framework repo.
23
24
  */
24
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
25
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, statSync, writeFileSync, } from 'node:fs';
25
26
  import { basename, dirname, join, resolve } from 'node:path';
26
27
  import { fileURLToPath, pathToFileURL } from 'node:url';
27
28
  /** Token substituted with the app name at copy time (in package.json name, README title, …). */
@@ -137,7 +138,8 @@ export function copyTemplate(srcDir, destDir, appName, report, relBase = '') {
137
138
  }
138
139
  /** Text extensions that get token substitution + utf8 handling. */
139
140
  function isTextFile(fileName) {
140
- return /\.(json|ts|js|mjs|cjs|md|txt|example|yml|yaml|gitignore)$/i.test(fileName) || fileName.startsWith('_');
141
+ return (/\.(json|ts|js|mjs|cjs|md|txt|example|yml|yaml|gitignore)$/i.test(fileName) ||
142
+ fileName.startsWith('_'));
141
143
  }
142
144
  /**
143
145
  * Names of the template's top-level SUBTREES that are copied separately (not
@@ -248,17 +250,20 @@ export function main(argv = process.argv.slice(2)) {
248
250
  console.log(' identity UI). You can still add any UI framework yourself later.');
249
251
  }
250
252
  console.log(' • The framework installed in server/ as immutable dependencies (@astram/core,');
251
- console.log(' @astram/guard, @astram/engine, @astram/sdk) — you never edit it; upgrade via');
253
+ console.log(' @astram/guard, @astram/engine, @astram/identity, @astram/migrate, @astram/sdk,');
254
+ console.log(' @astram/guide) — you never edit it; upgrade via');
252
255
  console.log(' `npm update`.');
253
256
  console.log(' • server/src/features/ — your editable API space. Add a feature by writing a');
254
257
  console.log(' Nest module/controller there and registering it in server/src/app.module.ts.');
255
258
  console.log(' • .astram/guide/ — your own, upgrade-safe project-rules space (ADR-0025).');
256
- console.log('\n (A turnkey login/session boilerplate ships in a later framework release;');
257
- console.log(' today the app gives you correct-by-default ENFORCEMENT out of the box.)');
259
+ console.log('\n Login, sessions, MFA and the identity admin are built in: enable them in');
260
+ console.log(' server/src/app.module.ts (see its comment block). Before production, read the');
261
+ console.log(' README "Production requirements" (emailSender, NODE_ENV, TRUST_PROXY, migrations).');
258
262
  console.log('\nNext steps:');
259
263
  console.log(` cd ${appName}/server`);
260
264
  console.log(' npm install');
261
- console.log(' npm run dev # boots the API; GET /health → 200, unclassified → 403');
265
+ console.log(' npm run dev # boots the API; GET /health → 200, GET /demo/public → 200');
266
+ console.log(' npm test # proves deny-by-default: an unclassified route is denied');
262
267
  if (withFrontend) {
263
268
  console.log('');
264
269
  console.log(` cd ${appName}/frontend`);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "create-astram-app",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "license": "MIT",
5
- "description": "Scaffolder for a new Astram app — emits a running, framework-enforced consumer project (empty src/features/ + deny-by-default enforcement) that installs the immutable @astram/core, @astram/guard, and @astram/sdk framework.",
5
+ "description": "Scaffolder for a new Astram app — emits a running, framework-enforced NestJS server (deny-by-default, built-in auth/identity to switch on) and, with --with-frontend, a React admin/auth UI, over the immutable @astram/* framework packages.",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "create-astram-app": "dist/index.js",
@@ -1,20 +1,24 @@
1
1
  # __APP_NAME__
2
2
 
3
- An **Astram consumer app**, scaffolded with `create-astram-app`. A monorepo with a
4
- `server/` (the API) and a `frontend/` (your UI). The API depends on the published,
5
- immutable framework packages ([`@astram/core`](https://www.npmjs.com/package/@astram/core),
3
+ An **Astram consumer app**, scaffolded with `create-astram-app`. A `server/` (the API) and,
4
+ if you scaffolded with `--with-frontend` or ran `astram-add-frontend`, a `frontend/` (the
5
+ identity UI). The API depends on the published, immutable framework packages
6
+ ([`@astram/core`](https://www.npmjs.com/package/@astram/core),
6
7
  [`@astram/guard`](https://www.npmjs.com/package/@astram/guard),
7
8
  [`@astram/engine`](https://www.npmjs.com/package/@astram/engine),
9
+ [`@astram/identity`](https://www.npmjs.com/package/@astram/identity),
10
+ [`@astram/migrate`](https://www.npmjs.com/package/@astram/migrate),
11
+ [`@astram/guide`](https://www.npmjs.com/package/@astram/guide),
8
12
  [`@astram/sdk`](https://www.npmjs.com/package/@astram/sdk)) and enforces
9
13
  **deny-by-default** from the very first boot. You build features; the framework lives
10
- read-only in `server/node_modules` and upgrades via `npm update` — you never edit it.
14
+ read-only in `node_modules` and upgrades via `npm update` — you never edit it.
11
15
 
12
16
  ## Layout
13
17
 
14
18
  ```
15
19
  __APP_NAME__/
16
20
  server/ the API (NestJS + the Astram framework enforcement)
17
- frontend/ your UI (empty — add Vite/React/Next/… and call the API)
21
+ frontend/ the identity UI (only with --with-frontend / astram-add-frontend)
18
22
  .astram/ your project-owned, upgrade-safe AI/dev guide (ADR-0025)
19
23
  docs/ your own docs (the scaffolder never clobbers this)
20
24
  ```
@@ -24,7 +28,7 @@ __APP_NAME__/
24
28
  ```bash
25
29
  cd server
26
30
  npm install
27
- npm run dev # boots the API (tsx watch) on http://localhost:3000
31
+ npm run dev # boots the API on http://localhost:3000 (sets NODE_ENV=development)
28
32
  ```
29
33
 
30
34
  Then:
@@ -32,15 +36,19 @@ Then:
32
36
  ```bash
33
37
  curl -i localhost:3000/health # 200 — @Public health probe
34
38
  curl -i localhost:3000/demo/public # 200 — explicit @Public() opt-out
35
- curl -i localhost:3000/demo/unclassified # 403 — DENIED (no classification)
36
39
  ```
37
40
 
38
- That last 403 is the whole point: **every route is denied unless you explicitly
39
- classify it.** Forgetting to declare a route locks the door instead of silently
40
- exposing it.
41
+ The scaffold ships no unclassified route (the demo one in
42
+ `src/health/demo.controller.ts` is commented out, so `/demo/unclassified` is a 404).
43
+ The point is: **every route is denied unless you explicitly classify it.** An
44
+ unclassified route gets 403 from the global guard, and once `IdentityFeatureModule`
45
+ is wired the app refuses to boot (`verifyGatable`). Forgetting to declare a route
46
+ locks the door instead of silently exposing it. `npm test`
47
+ (`test/enforcement.e2e.spec.ts`) proves both with a test-only controller.
41
48
 
42
49
  Other `server/` scripts: `npm run build` (→ `dist/`), `npm start` (run the build),
43
- `npm test`, `npm run lint`.
50
+ `npm test`, `npm run lint`, `npm run migration:run` / `migration:status` /
51
+ `migration:revert`.
44
52
 
45
53
  ## How the API wires the framework
46
54
 
@@ -58,10 +66,27 @@ export class AppModule {}
58
66
  ```
59
67
 
60
68
  `ShieldModule.forRoot()` binds the global deny-by-default guard (ADR-0002), the
61
- boot-pool assertion (ADR-0018), and the Core decision-authority token. You never
62
- re-implement enforcement — you register it once and add your controllers. Enable the
63
- full auth surface (login/MFA/refresh/logout) with `ShieldModule.forRoot({ auth: true,
64
- credentialResolver, decisionAuthority })`.
69
+ boot-pool assertion (ADR-0018), and the Core decision-authority token. With no options it
70
+ needs no database or Redis. To turn on login, sessions, MFA and the identity admin
71
+ (`/auth/*`, `/account/*`, `/identity/*`), follow the commented wiring in the header of
72
+ `server/src/app.module.ts`: `ShieldModule.forRoot({ auth: true, emailSender, rootIds,
73
+ identityActionKeys, identityControlPlaneKeys, recordAuthorization })` plus
74
+ `IdentityFeatureModule.forRoot({ rootIds, extraObjects })`. The framework provides the
75
+ credential store, MFA, session handling and the decision authority; you write none of them.
76
+
77
+ ### Before you deploy with auth on
78
+
79
+ - Pass an `emailSender` (or `'disabled'`): outside `NODE_ENV=development|test` boot fails
80
+ without one. Set `NODE_ENV=production` explicitly; `npm start` does not set it.
81
+ - Set `TRUST_PROXY` to your real proxy hop count, or the per-IP login/reset limits stay off.
82
+ - Set `REFRESH_HMAC_KEY` (a long random secret, never committed) and `REDIS_URL`. Redis is
83
+ required: the request path reads only Redis and fails closed when it is down.
84
+ - Pass the same `rootIds` (platform-admin user uuids, from config) to both `forRoot` calls.
85
+ - Run `npm run migration:run` with the DDL account (`DDL_DB_USER` / `DDL_DB_PASSWORD`) before
86
+ starting a new version. Add `--strict` in CI to fail on edited migrations.
87
+
88
+ The full list, and how to upgrade an app scaffolded with an earlier version, is in the
89
+ [`create-astram-app` README](https://www.npmjs.com/package/create-astram-app).
65
90
 
66
91
  ## Add a feature (the framework way)
67
92
 
@@ -69,18 +94,24 @@ credentialResolver, decisionAuthority })`.
69
94
  2. Register it in `server/src/app.module.ts` (add the module to `imports`, or its
70
95
  controller to `controllers`).
71
96
  3. **Classify every route:** `@Public()` for open routes, `@Classified({ typeKey,
72
- action })` for guarded ones. Anything unclassified is denied (403) by design.
97
+ action })` for guarded ones. Anything unclassified is denied by design (403; with
98
+ `IdentityFeatureModule` wired, the app refuses to boot).
73
99
  4. **Data access goes through the framework's RecordEngine** — never a raw DB pool.
74
- The `server/eslint.config.js` wall rule fails the build on off-road DB access.
100
+ The `server/eslint.config.mjs` wall fails lint on off-road DB access anywhere in
101
+ `src/**` except `app.module.ts` and `main.ts`.
75
102
  5. Add a test (see `server/test/` for the pattern).
76
103
 
77
104
  `server/src/features/` starts empty — it's your space.
78
105
 
79
106
  ## The frontend
80
107
 
81
- `frontend/` is intentionally empty — Astram is a **backend security kernel**, so it
82
- does not impose a UI framework. Add whatever you like and call the API. See
83
- `frontend/README.md` for the auth endpoints your UI will consume.
108
+ With `--with-frontend` (or `npx -p create-astram-app astram-add-frontend` from this
109
+ folder), `frontend/` holds a Vite/React identity UI: login with MFA and recovery codes,
110
+ forgot/reset password, account settings, and admin pages for companies, users, roles,
111
+ access, record policies, service accounts, cross-tenant grants and audit. It refreshes
112
+ expired access tokens on its own and ships a strict Content-Security-Policy. The views are
113
+ yours to edit; the logic updates through `@astram/frontend-core`. See
114
+ `frontend/FRONTEND.md`.
84
115
 
85
116
  ## The `.astram/guide/` directory
86
117
 
@@ -1,16 +1,26 @@
1
1
  # frontend
2
2
 
3
- Your UI lives here. This folder is intentionally empty — the Astram framework is a
4
- **backend security kernel**, so it does not impose a frontend framework. Add whatever
5
- you like (Vite + React, Next.js, SvelteKit, a mobile app's web build, …) and point it
6
- at the API in `../server` (default `http://localhost:3000`).
3
+ The Astram **identity UI** for this app: a Vite + React + shadcn/ui app scaffolded by
4
+ `create-astram-app --with-frontend` or `astram-add-frontend`. The files here are yours to
5
+ edit; the auth and API logic comes from `@astram/frontend-core` and `@astram/sdk` and
6
+ updates with `npm update`. See [`FRONTEND.md`](./FRONTEND.md) for the update, no-clobber
7
+ and re-skin model.
7
8
 
8
- The API's auth surface is ready to consume:
9
+ ```bash
10
+ npm install
11
+ npm run dev # http://localhost:5173; proxies /api → http://localhost:3000 (API_URL to override)
12
+ ```
9
13
 
10
- - `POST /auth/login` `{ identityHint, password }` → `{ session, tokens: { accessToken, refreshToken } }`
11
- - `POST /auth/refresh` `{ refreshToken }` → new tokens
12
- - `POST /auth/logout` `{ sessionId }` → 204
13
- - Protected routes: send `Authorization: Bearer <accessToken>`. A `@Classified` route
14
- is enforced by the framework — no token → 401, denied by policy → 403.
14
+ Start the API (`../server`) first, with auth turned on, or there is nothing to sign in to.
15
15
 
16
- See `../server/src/features/` for the API features your UI will call.
16
+ What it includes:
17
+
18
+ - Login, MFA challenge (TOTP or a recovery code), forced re-enrolment after a recovery-code
19
+ login, forgot password, reset password.
20
+ - Account: profile, change password, two-factor devices and recovery codes.
21
+ - Admin pages, shown only when your roles allow them: companies, users (memberships and
22
+ role postings), roles, access, record policies, service accounts, cross-tenant grants,
23
+ audit.
24
+ - Token refresh: a 401 refreshes once and retries (single-flight, shared across tabs).
25
+ - A strict Content-Security-Policy in `index.html`. If the API is not served same-origin
26
+ under `/api`, add its origin to `connect-src`.
@@ -2,6 +2,22 @@
2
2
  <html lang="en" suppressHydrationWarning>
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
+ <!--
6
+ Content-Security-Policy (D11). The session tokens live in localStorage, so no script
7
+ may run unless it is served from this origin: no inline scripts, no eval, no third-party
8
+ script hosts. Allowed beyond 'self':
9
+ style-src 'unsafe-inline' the UI kit (sonner, Radix scroll lock) injects <style> tags
10
+ fonts.googleapis/gstatic the Inter/JetBrains Mono import in src/index.css
11
+ img-src data: blob: the MFA QR code is a data: URL
12
+ `npm run dev` relaxes script-src/connect-src for Vite's React-refresh preamble and HMR
13
+ websocket (see `devCsp` in vite.config.js); the built app gets this policy unchanged.
14
+ Add an API origin to connect-src if the frontend calls one other than same-origin /api.
15
+ frame-ancestors cannot be set in a <meta>; send it (or X-Frame-Options) as a header.
16
+ -->
17
+ <meta
18
+ http-equiv="Content-Security-Policy"
19
+ content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: blob:; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'"
20
+ />
5
21
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
22
  <link rel="icon" type="image/png" href="/favicon.png" />
7
23
  <title>__APP_NAME__</title>
@@ -12,7 +12,7 @@
12
12
  "test": "node --test src/**/*.test.mjs"
13
13
  },
14
14
  "dependencies": {
15
- "@astram/frontend-core": "^0.3.0",
15
+ "@astram/frontend-core": "^0.5.0",
16
16
  "@astram/sdk": "^0.2.0",
17
17
  "@radix-ui/react-alert-dialog": "^1.1.19",
18
18
  "@radix-ui/react-avatar": "^1.1.10",