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:
@@ -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
|
||||||
@@ -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]].
|
||||||
@@ -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.
|
||||||
@@ -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]].
|
||||||
@@ -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 P0–P8 (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]].
|
||||||
@@ -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`.
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user