docs: add repo-local project memory under .claude/memory/

Versioned, per-topic project memory (index + entries): IIOS overview, the generic-safety
rule, run/test + the replay.spec flake workaround, recent features (Supabase auth,
reactions/pins/saves, mentions, media, notifications), the chat-web consumer, and workflow
conventions. CLAUDE.md points to it as the accumulating-notes companion to the canonical rules.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 19:55:38 +05:30
parent 58ebaf1982
commit 5abee1b5b7
8 changed files with 168 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
# IIOS Project Memory — Index
Repo-local, versioned project memory. The full canonical rules are in the repo root
**`CLAUDE.md`**; these files are granular, per-topic memories that accumulate across sessions.
Read the relevant ones before working in that area; add/update files as the project evolves.
- [project_iios_overview.md](project_iios_overview.md) — what IIOS is (generic interaction OS; kernel + specializations + platform ports)
- [feedback_generic_safety.md](feedback_generic_safety.md) — THE #1 rule: no chat/domain vocabulary in the kernel
- [reference_run_and_test.md](reference_run_and_test.md) — run command, isolated `iios_test` DB, and the `replay.spec` flake workaround
- [project_recent_features.md](project_recent_features.md) — the "real-providers" era: Supabase auth, reactions/pins/saves, mentions→inbox, media, notifications
- [reference_chat_web_consumer.md](reference_chat_web_consumer.md) — chat-web is the reference app driving IIOS feature work
- [feedback_workflow.md](feedback_workflow.md) — commits (email + co-author), IIOS_DEV_TOKENS off in prod, TDD, build-before-restart
+28
View File
@@ -0,0 +1,28 @@
---
name: feedback_generic_safety
description: THE #1 locked rule — the kernel must never hardcode chat/domain vocabulary
metadata:
type: feedback
---
**The kernel must stay generic.** No `'dm'` / `'group'` / `'reaction'` / `'emoji'` / `'mention'`
literals in kernel or messaging *logic*. If a reviewer asked "is this a chat backend now?" the
answer must stay **no**.
**Why:** IIOS is a generic interaction OS; chat is one consumer. Baking chat meaning into the
kernel destroys reuse (support/community/meetings share the same core).
**How to apply:** domain meaning lives in exactly three places, never the kernel —
1. **OPA policy** (`DevOpaPort` → real OPA): DM-cap, group-admin, governed-join, media limits,
notification triggers.
2. **Opaque attributes** the kernel stores but never interprets: `thread.metadata.membership`
(`dm`/`group`), interaction annotations (opaque `annotationType`+`value` → app writes
`reaction`/`pin`/`save`), `mentions[]` (opaque userId notify-list; kernel never parses `@`).
3. **The app** (chat-web): rendering + product semantics.
Reading an opaque attr inside a **policy/notification gate** (`membership === 'dm'` in
`DevOpaPort` or `notification.projector.ts`) is OK — that file IS the policy plane. Everywhere
else, keep generic. Verify before committing:
`grep -rniE "'dm'|'group'|reaction|emoji" packages/iios-service/src | grep -v spec` — hits only
in policy/notification/app-facing layers or comments. Also run `pnpm boundary`.
Related: [[project_iios_overview]].
+19
View File
@@ -0,0 +1,19 @@
---
name: feedback_workflow
description: Working conventions — commits, prod flags, TDD, rebuild-before-restart
metadata:
type: feedback
---
- **Commits:** conventional (`feat:`/`fix:`/`docs:`/`chore:`), git email
**`maaz@insigniaconsultancy.com`**, co-author every commit with Claude. The user commits
directly to `main` in this project (fine); branch only if asked.
- **⚠ `IIOS_DEV_TOKENS` MUST be `0`/unset in production** — it exposes `/v1/dev/*` (unauth token
minting, chaos, retention sweep). The single most important prod-hardening flag.
- **TDD** — write the failing spec first; verify it fails; implement; verify it passes.
- **Rebuild before restart** — after backend changes, `nest build` then restart from `dist`;
`lsof -ti :3200 | xargs kill -9` first or the old build keeps serving (stale-dist bites).
- **New kernel capability = a generic primitive only** — add domain meaning in OPA policy + the
app, never the kernel. See [[feedback_generic_safety]].
- The user prefers **direct, fast iteration** (implement → verify end-to-end → commit), not
heavyweight multi-agent/spec ceremony. Include "how to test" in summaries; report failures honestly.
+23
View File
@@ -0,0 +1,23 @@
---
name: project_iios_overview
description: What IIOS is — a generic multi-tenant interaction OS; kernel + specializations + swappable platform ports
metadata:
type: project
---
IIOS (Insignia Interaction OS) = one NestJS service (`@insignia/iios-service`) + SDKs, in a
pnpm monorepo (`packages/*`). Every interaction (chat message, ticket, routed post, AI
suggestion, meeting) is the **same kernel object** inside a **tenant scope** (`IiosScope`:
org/app/tenant/…), behind the **same fail-closed gates**, emitting the **same audit trail**.
Products (messaging, inbox, support, routing, AI, calendar, media, notifications) are thin
**specializations** on top of a tiny kernel — never the reverse (`pnpm boundary` enforces it).
Platform seams are **ports** (`IiosPlatformPorts`, DI token `PLATFORM_PORTS`; dev = permissive
`LocalDevPorts`): session, opa, cmp (consent), mdm, sas, capability, plus `StoragePort` (media)
and `NotificationPort` (push). **Dev stubs swap to real adapters with zero consumer changes.**
Every op passes `decideOrThrow(ports, {action,…})` fail-closed. Events go through a
transactional outbox → `OutboxBus` → idempotent projectors (inbox, notifications).
See the repo `CLAUDE.md` and `docs/IIOS_API_AND_SDK_GUIDE.md` (as-built reference) for detail.
Related: [[feedback_generic_safety]].
+31
View File
@@ -0,0 +1,31 @@
---
name: project_recent_features
description: The "real-providers" era — Supabase auth, reactions/pins/saves, mentions→inbox, media, notifications
metadata:
type: project
---
Beyond P0P8 (kernel → messaging → inbox → support → adapters → routing → AI →
calendar/meetings), recent work (mostly driven by the chat app, the start of P9 "real
providers"):
- **Real Supabase auth** — `SessionVerifier` verifies real OIDC tokens against issuer JWKS
(ES256, no secret), a **multi-issuer registry** routed by the `iss` claim → per-issuer `appId`
scope (`AUTH_ISSUERS` JSON, or `SUPABASE_URL` single-issuer shorthand). `userId = email`.
Legacy HS256 app-token path (`APP_SECRETS`) stays for dev/tests.
- **Reactions / pins / saves** — one generic `IiosInteractionAnnotation` primitive (opaque
`annotationType`+`value`); socket `annotate` event → `annotation` broadcast;
`GET /v1/threads/my-annotations?type=save`.
- **@mentions → Inbox** — `send(... mentions[])` (opaque userId list) → `InboxProjector` fans out
a `MENTION` inbox item to mentioned participants; reading resolves it.
- **Media** — `StoragePort` (dev = local disk `MEDIA_DIR`; prod swap to S3/Supabase), presigned
upload/download (signed HS256 tokens, OPA-gated size/type, tenant-fenced), `attachment` on
`MessageDto`; parts use generic `MEDIA_REF/VOICE_REF/FILE_REF`.
- **Notifications** — presence-gated Web Push: `NotificationProjector` runs 3 gates
(policy=DM/mention/reply-to-you · presence=`focus_thread` signal · per-thread `muted`) →
swappable `NotificationPort` (Web Push/VAPID); dead sub (410) pruned. Presence is in-memory
(single-instance) → Redis for multi-replica.
- `senderId` (stable externalId) on `MessageDto` for reliable "is this mine?".
~205 tests. Keep `docs/IIOS_API_AND_SDK_GUIDE.md` current when adding endpoints.
Related: [[reference_chat_web_consumer]], [[feedback_generic_safety]].
@@ -0,0 +1,20 @@
---
name: reference_chat_web_consumer
description: chat-web is the reference consumer app that drives IIOS feature work
metadata:
type: reference
---
**chat-web** (separate repo, `~/Documents/insignia-work/chat-web`) is the reference app on IIOS —
a 1:1 + group chat UI (Vite + React + TanStack Router/Query + socket.io-client + supabase-js).
It's frontend-only; IIOS provides identity, threads, messages, realtime, reactions, mentions,
media, notifications.
Feature work usually spans **both repos**: a generic primitive/port in iios + the app UI in
chat-web. The layer split we follow: **service** owns storage/auth/governance, the **SDK layer**
(`chat-web/src/lib/*`, mirrors `@insignia/iios-kernel-client`) owns client plumbing
(e.g. `uploadMedia`/`mediaUrl`, `registerPush`), the **app** owns rendering.
chat-web uses real Supabase login (`VITE_SUPABASE_URL` + anon key in its `.env`); identity =
email. Run it with `pnpm dev`. Commit both repos with git email `maaz@insigniaconsultancy.com`.
Related: [[project_recent_features]].
+30
View File
@@ -0,0 +1,30 @@
---
name: reference_run_and_test
description: How to run the service + the test-DB isolation and the replay.spec flake workaround
metadata:
type: reference
---
**Infra:** Postgres in docker `iios-db` on **:5434** (db `iios`), Redis on :6379. If Docker is
down: `open -a OrbStack` then `docker start iios-db`.
**Run** (dev auth via Supabase; media + push enabled):
```
pnpm --filter @insignia/iios-service exec nest build # rebuild after backend changes
SUPABASE_URL=https://<ref>.supabase.co REDIS_URL=redis://localhost:6379 PORT=3200 \
APP_SECRETS='{"portal-demo":"dev-secret"}' MEDIA_DIR=/tmp/iios-media \
VAPID_PUBLIC_KEY=… VAPID_PRIVATE_KEY=… VAPID_SUBJECT=mailto:dev@insignia \
node packages/iios-service/dist/main.js # :3200 ; GET /health
```
Restarting: `lsof -ti :3200 | xargs kill -9` first (stale instance → EADDRINUSE / old build served).
**Tests:** `pnpm test` (Vitest) runs against an **isolated `iios_test` DB** (globalSetup creates
+ migrates it; `DATABASE_URL` overridden) — it **never wipes the dev `iios` DB**. TDD: spec next
to code; DB specs use `resetDb()`.
**⚠ Known flake — `outbox/replay.spec`:** clock/ordering-sensitive, pre-existing. If it fails in a
full run, it's stale `iios_test` state, NOT a regression. Fix:
`docker exec iios-db psql -U iios -d postgres -c "DROP DATABASE IF EXISTS iios_test WITH (FORCE)"`
then re-run. Prove it's not yours by stashing changes and re-running.
`pnpm boundary` = import-boundary check (must stay OK). Smokes: `packages/iios-service/scripts/smoke-*.mjs`.
+5
View File
@@ -1,5 +1,10 @@
# IIOS — Claude Code Rules # IIOS — Claude Code Rules
> **Project memory:** granular, versioned per-topic notes live in **`.claude/memory/`** — read
> `.claude/memory/MEMORY.md` (the index) and the relevant entries before working in an area, and
> add/update memories as the project evolves. This file is the canonical rules; those are the
> accumulating notes.
## What IIOS is ## What IIOS is
**IIOS (Insignia Interaction OS)** is a **generic, multi-tenant "interaction OS"** — one **IIOS (Insignia Interaction OS)** is a **generic, multi-tenant "interaction OS"** — one