indira-workspace-ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: indira-api
3
- description: Scaffold and extend Node/Express backend services in the Indira API architecture — routes/controller/service/repository/model layering, validated per-environment config, PM2 process definitions, and Pino structured HTTP logging with an audit trail on every mutation. Ensures every backend app shares the same folder structure and constraints. Use for any new Express service, or any new module (patient, auth, appointment, audit, billing, ...) added to an existing one.
3
+ description: Scaffold and extend Node/Express backend services in the Indira API architecture — routes/controller/service/repository/model layering, validated per-environment config, PM2 process definitions, and Pino structured HTTP logging with an audit trail on every mutation. Includes a ready-made SSO-with-approval-gate auth pattern (env-configured super-admin email allowlist, new users pending until approved). Ensures every backend app shares the same folder structure and constraints. Use for any new Express service, any new module (patient, auth, appointment, audit, billing, ...) added to an existing one, or the backend half of a new full-stack app (pair with /indira-ui for the frontend).
4
4
  ---
5
5
 
6
6
  # indira-api
@@ -10,6 +10,12 @@ The full spec lives at `docs/api-architecture.md` in the target repository —
10
10
  read it completely before doing anything else; every path, filename and rule
11
11
  you need is in it, and this skill does not repeat them.
12
12
 
13
+ **Building a brand-new full-stack app?** Scaffold the backend first —
14
+ `auth` and `audit` before any domain module (§13 of the spec) — then hand
15
+ off to `/indira-ui` for the frontend. That skill designs the screens; it
16
+ doesn't invent the data they show, so the API should exist (even just
17
+ scaffolded and booting) before it starts.
18
+
13
19
  Your job has four parts, in order. Do not skip Part 0 or Part 1.
14
20
 
15
21
  ## Part 0 — Establish the spec (new repo only)
@@ -39,11 +45,15 @@ Do not scaffold from a one-line request. For a **new service**, confirm:
39
45
  specific frontend, another internal service, a cron, a webhook)?
40
46
  - **Database** — Postgres, MySQL, MongoDB, something else? Driver or ORM
41
47
  preference, or should it match another Indira service for consistency?
42
- - **First modules** — beyond the mandatory `auth` and `audit` (§12 of the
48
+ - **First modules** — beyond the mandatory `auth` and `audit` (§13 of the
43
49
  spec builds these first), which domain modules does the initial version
44
50
  need? Get the entity name and its core fields for each.
45
51
  - **Auth model** — session, JWT, SSO against an existing identity provider?
46
- Anything from an existing Indira service to reuse rather than reinvent?
52
+ If it's SSO with an approval gate (a new user is `pending` until a super
53
+ admin approves them; an env-configured email allowlist grants super-admin
54
+ on first login) that exact pattern is §12 of the reference spec — read it
55
+ before scaffolding `auth`, don't design it from scratch. Anything from an
56
+ existing Indira service to reuse rather than reinvent?
47
57
  - **Environments** — which of local/uat/production does this need on day
48
58
  one, and are there secrets beyond DB + mail that the env schema must
49
59
  declare?
@@ -119,7 +129,7 @@ If any answer is no, fix the plan before writing code.
119
129
  key the config schema declares has a placeholder.
120
130
  8. Write one integration test per new route under `tests/`, and unit tests
121
131
  for the service's business rules beside the module.
122
- 9. Verify (§12 of the spec): the server boots, `GET /api/health` returns
132
+ 9. Verify (§13 of the spec): the server boots, `GET /api/health` returns
123
133
  200, one request produces one structured Pino log line carrying a
124
134
  request id, and a deliberately-triggered error returns the `{ error:
125
135
  { code, message, requestId } }` shape with that same id.
@@ -311,10 +311,80 @@ gitignored `.env.*` files and in the box's process environment — never in
311
311
  the spec doesn't have, the answer is usually the existing pattern used
312
312
  plainly. Extend this document (and every app's copy of it) before
313
313
  inventing a one-off.
314
+ 9. **The super-admin allowlist lives in env, not the database.**
315
+ `SUPER_ADMIN_EMAILS` (§12.1) is read at boot and re-checked on every SSO
316
+ login — never exposed as an editable field, never granted through an API
317
+ call.
314
318
 
315
319
  ---
316
320
 
317
- ## 12. Building it for a new app
321
+ ## 12. SSO authentication with an approval gate
322
+
323
+ A pattern for services that authenticate against a corporate identity
324
+ provider (reference IdP: Microsoft Entra ID / Azure AD, via OIDC) instead of
325
+ issuing their own passwords, and that gate a brand-new user behind a human
326
+ approval before they can do anything.
327
+
328
+ ### 12.1 Config
329
+
330
+ `config/index.js`'s schema declares, alongside the existing keys:
331
+
332
+ ```
333
+ SSO_TENANT_ID required
334
+ SSO_CLIENT_ID required
335
+ SSO_CLIENT_SECRET required
336
+ SSO_REDIRECT_URI required
337
+ SUPER_ADMIN_EMAILS required, comma-separated, lower-cased and trimmed on read
338
+ ```
339
+
340
+ `SUPER_ADMIN_EMAILS` is the one allowlist that grants the `super_admin`
341
+ role. It is never stored in the database and never editable from the API —
342
+ the only way to change who is a super admin is to change this env var and
343
+ redeploy. That is deliberate: the people who can approve new accounts must
344
+ themselves be provisioned outside the thing they administer.
345
+
346
+ ### 12.2 Flow
347
+
348
+ 1. `GET /api/auth/sso/login` redirects to the IdP's OIDC authorize endpoint
349
+ (state + PKCE verifier stored server-side, keyed by a short-lived cookie).
350
+ 2. `GET /api/auth/sso/callback` exchanges the code, validates the id_token
351
+ (issuer, audience, signature, nonce), and extracts the verified email.
352
+ 3. Look the email up in `users`:
353
+ - **Not found, and email ∈ `SUPER_ADMIN_EMAILS`** — create the user with
354
+ `role: "super_admin"`, `status: "active"`, issue the session/JWT +
355
+ refresh token immediately.
356
+ - **Not found, and email ∉ `SUPER_ADMIN_EMAILS`** — create the user with
357
+ `status: "pending"`, `role: "member"`. Do **not** issue a session.
358
+ Respond `202 { data: { status: "pending" } }` — the client shows a
359
+ "waiting for approval" screen, not an error.
360
+ - **Found, `status: "active"`** — issue session/JWT + refresh token as
361
+ normal. If email ∈ `SUPER_ADMIN_EMAILS` and the stored role isn't
362
+ `super_admin` yet, elevate it on this login too — the allowlist is
363
+ always the source of truth for who is a super admin, even for rows
364
+ created before an email was added to it.
365
+ - **Found, `status: "pending"`** — respond `202` again, same as a brand
366
+ new pending user. No session.
367
+ - **Found, `status: "rejected"`** — `403`. A rejected user is not
368
+ silently re-queued by logging in again.
369
+ 4. A `super_admin` calls `GET /api/users?status=pending` to see the queue,
370
+ and `POST /api/users/:id/approve` or `POST /api/users/:id/reject` to
371
+ resolve one. Approve flips `status` to `active` (the user's *next* SSO
372
+ login then issues a session); reject flips it to `rejected`. Both routes
373
+ sit behind `auth("user:approve")`, restricted to `super_admin`, and both
374
+ write to the audit trail (actor, the user approved/rejected, before/after
375
+ status) — this is a mutation like any other, law 5 applies.
376
+
377
+ ### 12.3 What this buys, and what it deliberately doesn't
378
+
379
+ This is a gate, not a role system — every approved user is a plain member
380
+ until something else grants them more. Fine-grained permissions beyond
381
+ "super admin vs. everyone else" are a separate module's concern (or a later
382
+ addendum to this one), not something to bolt onto `auth` because it's
383
+ already open.
384
+
385
+ ---
386
+
387
+ ## 13. Building it for a new app
318
388
 
319
389
  1. Scaffold the tree in §1 exactly. Nothing above `modules/*` beyond what's
320
390
  listed.
@@ -1,16 +1,46 @@
1
1
  ---
2
2
  name: indira-ui
3
- description: Design and build screens in the Indira Workspace UI language. Interviews the developer or business team first (who uses it, what they come to do, what must be found in two seconds), turns the answers into a component hierarchy that shows no more data than the task needs, then builds it from the design-system spec. Use for any new page, dashboard, form, list, or internal tool that should look and behave like the BRD Governance Tool.
3
+ description: Design and build screens from this repo's design-system spec(s) — Indira Workspace UI (light, the default) and, where the repo has it, Vault UI (dark, for custody/treasury/compliance-grade data) — asking which composition to use when more than one is available. Interviews the developer or business team first (who uses it, what they come to do, what must be found in two seconds), turns the answers into a component hierarchy that shows no more data than the task needs, then builds it from the chosen spec. Use for any new page, dashboard, form, list, or internal tool; migrating an existing screen's UI to this design language; or the frontend half of a new full-stack app (pair with /indira-api for the backend).
4
4
  ---
5
5
 
6
6
  # indira-ui
7
7
 
8
- You are a senior product designer who builds. You work in the **Indira
9
- Workspace UI** language, specified in `docs/design-system.md` in this
10
- repository. Read that file completely before doing anything else; every
11
- number and rule you need is in it, and this skill does not repeat them.
12
-
13
- Your job has three parts, in order, and you do not skip the first one.
8
+ You are a senior product designer who builds. A repo can define more than
9
+ one design composition which one you build in is decided in Part 0, below.
10
+ Whichever one is chosen, read its spec file completely before doing anything
11
+ else; every number and rule you need is in that one file, and this skill
12
+ does not repeat them.
13
+
14
+ Your job has four parts, in order, and you do not skip Part 0 or Part 1.
15
+
16
+ ## Part 0 — Pick the design composition
17
+
18
+ Check the target repo for `docs/design-system*.md`.
19
+
20
+ - **Exactly one file** — that is the composition. Read it completely and go
21
+ to Part 1; don't make the developer confirm a choice they don't have.
22
+ - **More than one file** — read enough of each (title + opening paragraph)
23
+ to describe it in a sentence, then ask the developer which this screen
24
+ should use before doing anything else. As of this writing, a repo may
25
+ offer:
26
+ - **Indira Workspace UI** (`docs/design-system.md`) — light, one rose
27
+ accent, soft rounded shapes. The default: governance/workflow tools,
28
+ anything that should look like the BRD Governance Tool.
29
+ - **Vault UI** (`docs/design-system-vault.md`) — dark by default, one
30
+ desaturated accent, dense tabular layout. Custody/treasury/compliance-
31
+ grade screens where the data itself carries the seriousness and a
32
+ light, friendly surface would undersell that.
33
+
34
+ List whatever compositions the repo actually has, not just these two —
35
+ more may exist by the time you read this. Wait for an explicit answer.
36
+ If the developer has no preference, recommend Indira Workspace UI and say
37
+ why (it's this product's established look); switch only on request.
38
+ - **No file** — fresh project. Fall back to building Indira Workspace UI
39
+ from this skill's own copy of the spec (§7), same as if this part didn't
40
+ exist.
41
+
42
+ Never mix components from two compositions on one screen — each spec's own
43
+ closing section says so, and it's as true across systems as within one.
14
44
 
15
45
  ## Part 1 — Grill before you draw
16
46
 
@@ -20,6 +50,29 @@ not one at a time, and stop as soon as the answers are clear — this is a
20
50
  discovery, not a form. Use the question tool when one is available; otherwise
21
51
  ask in prose and wait.
22
52
 
53
+ **Migrating an existing screen, not building a new one?** Same three parts,
54
+ but the brief opens differently — add these before "Who":
55
+
56
+ - **What's there today** — describe or screenshot the current screen. What
57
+ do people actually use vs. ignore? (Ask directly — the ignored parts are
58
+ what you leave out, exactly as with a fresh build.)
59
+ - **What must not change** — which behaviours, data, or integrations are
60
+ load-bearing and must survive untouched? A migration rebuilds the visual
61
+ and structural layer; it is not licence to rewrite what the screen does.
62
+ - **What's the current stack** — plain CSS, Bootstrap, MUI, styled-
63
+ components? None of its styling survives the swap; what you're checking
64
+ for is which existing data-fetching/behaviour logic can stay as-is
65
+ underneath the new markup.
66
+
67
+ Migrate one screen at a time. "Migrate the whole app" is always several
68
+ screens — say so, and ask which one first. An old screen and a newly
69
+ migrated one looking different in the same nav is normal mid-migration, not
70
+ a bug to fix immediately.
71
+
72
+ **Building a brand-new full-stack app?** If there's no backend yet, run
73
+ `/indira-api` first (it scaffolds `auth` and `audit` before any domain
74
+ module) — this skill designs screens, it doesn't invent the data they show.
75
+
23
76
  **Who**
24
77
  - Who opens this screen, by role? How often — several times a day, once a
25
78
  week, once a quarter?
@@ -130,20 +183,25 @@ Build from the spec, not from memory of other design systems.
130
183
 
131
184
  ## What "done" looks like
132
185
 
133
- Give back, in this order: the confirmed brief, the hierarchy tree, the
134
- screens built, the audit result, and a two-line note of any place the request
135
- was pushed back on and what was decided. If a requested element was left out
136
- for a law, name the law the requester should be able to overrule it
137
- knowingly, not discover it missing.
186
+ Give back, in this order: which design composition was used (and, if more
187
+ than one was on offer, that the developer chose it), the confirmed brief,
188
+ the hierarchy tree, the screens built, the audit result, and a two-line note
189
+ of any place the request was pushed back on and what was decided. If a
190
+ requested element was left out for a law, name the law — the requester
191
+ should be able to overrule it knowingly, not discover it missing.
138
192
 
139
193
  ## Things you never do
140
194
 
195
+ - Assume the design composition when the repo defines more than one — Part
196
+ 0 is not optional just because you're confident which one fits.
141
197
  - Add a page-name heading, a hero, a gradient, an emoji icon, or a second
142
198
  filled button.
143
199
  - Write a sentence of help text under a control.
144
200
  - Show an id, a status word and a status colour for the same record in the
145
201
  same place.
146
- - Invent a colour for a new status. Six statuses; a seventh is a product
147
- decision, not a design one.
202
+ - Invent a colour for a new status beyond what the chosen composition's own
203
+ spec defines — a new one is a product decision, not a per-screen one.
148
204
  - Use a spinner for page content, or animate anything on a loop.
149
205
  - Design a screen for a user you have not asked about.
206
+ - Reach for a second composition's component inside a screen built in the
207
+ first one.
package/README.md CHANGED
@@ -4,6 +4,15 @@ The component library specified in [docs/design-system.md](docs/design-system.md
4
4
  React 19 + Tailwind CSS 4 + Lucide. Published to npm as `indira-workspace-ui`, and it doubles
5
5
  as an installer for the `indira-ui` and `indira-api` Claude Code skills.
6
6
 
7
+ This repo also holds a second, deliberately separate composition — **Vault UI**
8
+ ([docs/design-system-vault.md](docs/design-system-vault.md), components in
9
+ [src/vault/](src/vault/)) — dark, one accent, dense tabular layout, for
10
+ custody/treasury/compliance-grade screens where a light, friendly surface
11
+ would undersell the data. See it live at the "Vault UI" nav item in the demo
12
+ workspace. The `/indira-ui` skill now asks which composition to use before
13
+ building a screen whenever a repo has more than one. Vault UI is not part of
14
+ the published npm package yet — it's source-only in this repo for now.
15
+
7
16
  ## Install in a consuming project
8
17
 
9
18
  ```
@@ -55,6 +64,7 @@ npm run build:lib # builds the publishable package into dist-lib/
55
64
  | `src/components/` | One file per component; `index.js` is the barrel and the library's entry point. |
56
65
  | `src/screens/` | The demo workspace: Dashboard, BRD list, BRD detail, a library gallery per component group, and the dev-skills docs screen. |
57
66
  | `src/data/` | Demo directory and BRD records (demo app only — not part of the published package). |
67
+ | `src/vault/` | Vault UI — the second design composition. Its own tokens/components, scoped under `.vault`, never mixed with `src/components/`. |
58
68
  | `.claude/skills/indira-ui`, `.claude/skills/indira-api` | The two Claude Code skills this package installs into consumer projects. |
59
69
  | `bin/cli.js` | The `indira-workspace-ui add-skills` CLI. |
60
70
  | `vite.lib.config.js` | Library build config — components only, externalizes `react`/`react-dom`/`lucide-react`. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indira-workspace-ui",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "description": "Indira Workspace UI — the component library specified in docs/design-system.md, plus a CLI to install the indira-ui and indira-api Claude Code skills",