diff --git a/docs/adr/0001-support-service-to-iios-naming-migration.md b/docs/adr/0001-support-service-to-iios-naming-migration.md new file mode 100644 index 0000000..7cb31ee --- /dev/null +++ b/docs/adr/0001-support-service-to-iios-naming-migration.md @@ -0,0 +1,107 @@ +# ADR-0001: `support-service` → IIOS naming migration + +- **Status:** Accepted +- **Date:** 2026-07-03 +- **Deciders:** IIOS core +- **Context tags:** naming, packaging, migration, KG-16 + +## Context + +IIOS (Insignia Interaction OS) is the greenfield realization of a vision first +prototyped in the standalone **`support-service`** app. That prototype already stated the +core idea — *"Everything is a message: a generic Message core (conversation / message / +channel / user) is the foundation; Support (ticket / agent / callback) is a thin +specialization on top"* — but it did so with **support-centric naming** and as a +single-purpose support desk. + +IIOS generalizes that same idea to an **interaction OS** of much broader scope +(messaging, inbox, routing, AI enrichment, calendar, plus support as *one* +specialization among many). During P0–P9 it landed a clean, generic vocabulary: +an `Iios`-prefixed persistence layer and `@insignia/iios-*` packages. + +Two problems make an explicit decision necessary: + +1. **Naming drift.** The prototype and IIOS use different words for the same concepts + (`Conversation` vs `IiosThread`, `Message` vs `IiosInteraction` + `IiosMessagePart`, + `User` vs `IiosSourceHandle` + `IiosActorRef`). Without a canonical mapping, contributors + coming from the prototype reintroduce support-centric names, and host apps don't know + which SDK is authoritative. +2. **KG-16 — "support wedge evidence overgeneralized."** The critics' analysis flags the + risk of treating the `support-service` architecture as proof of *all* IIOS capabilities. + Support is a **specialization**, not the core; the naming must make that structural + (support names are namespaced *under* the generic core, never the core itself). + +An unresolved sub-question also blocks packaging: the workspace scope was historically +ambiguous between `@insignia/*` and `@lynkeduppro/*`. + +## Decision + +**1. Canonical vocabulary is interaction-centric and `Iios`-namespaced.** +The generic core is the noun set already shipped in `@insignia/iios-service`: +`IiosScope`, `IiosSourceHandle`/`IiosActorRef`, `IiosChannel`, `IiosThread`, +`IiosInteraction`/`IiosMessagePart`. **Support is a specialization layered on top** and is +always namespaced as such (`IiosSupport*`, `IiosTicket*`, `IiosCallbackRequest`) — never +promoted to a core concept. "Conversation" and support-centric "Message-as-ticket" framing +are retired. + +**2. Package scope is `@insignia/iios-*`.** This resolves the `@insignia` vs `@lynkeduppro` +ambiguity in favour of `@insignia`. All IIOS packages already follow `@insignia/iios-`; +that is now the standard. + +**3. Migration is greenfield-and-deprecate (strangler), not rename-in-place.** +`support-service` is **frozen legacy** — we do not rename its models or ship a new version of +it. New work happens in IIOS; host apps cut over to the `@insignia/iios-*` SDKs feature-by- +feature. `support-service` is retired once every host app it serves has migrated. + +### Canonical naming map (legacy → IIOS) + +| `support-service` (legacy) | IIOS (canonical) | Note | +|---|---|---| +| `Channel` | `IiosChannel` | generic ingress/egress channel | +| `User` | `IiosSourceHandle` + `IiosActorRef` | identity split: external handle vs resolved actor | +| `Conversation` | `IiosThread` | "conversation" retired; thread is generic | +| `Message` | `IiosInteraction` + `IiosMessagePart` | envelope vs content parts | +| `Attachment` | `IiosMessagePart` (`kind=MEDIA`, `contentRef`) | attachments are just parts | +| `Team` / `TeamMember` | `IiosSupportQueue` / `IiosSupportTeamMember` | **support specialization**, namespaced | +| `ConversationAssignment` | support assignment (`IiosSupport*`) | specialization, not core | +| `Ticket` / `TicketConversation` | `IiosTicket` / `IiosTicketThreadLink` | ticket links to generic threads | +| `CallbackRequest` | `IiosCallbackRequest` | | +| `Meeting` | `IiosMeeting` (+ P8 calendar models) | promoted to first-class in IIOS | +| `Notification` | `notification_outbox` (planned) | not yet built in IIOS | +| `ProcessedCommand` | `IiosProcessedEvent` + `IiosIdempotencyCommand` | consumer ledger vs command ledger | +| `KnowledgeArticle` | (deferred — AI/RAG) | out of current scope | + +### Rules going forward + +- **Every persisted model is `Iios`-prefixed.** No un-prefixed domain models. +- **Support (and any future vertical) is namespaced under the generic core**, never the other + way round. If a name reads as "support-only," it must carry the `IiosSupport*`/`IiosTicket*` + prefix and depend on the core — the core never depends on it (enforced by the import-boundary + check). +- **New packages are `@insignia/iios-`.** +- **Legacy references** in prose cite `support-service` explicitly as *legacy*, with a pointer + to this ADR. + +## Consequences + +**Positive** +- One authoritative vocabulary; contributors from the prototype have a lookup table. +- KG-16 is structurally addressed: support cannot masquerade as the core because its names are + subordinate and the boundary check enforces the dependency direction. +- Packaging is unblocked (`@insignia/iios-*` is canonical). +- No risky in-place rename of a running legacy service; cutover is incremental per host app. + +**Negative / costs** +- Two systems coexist during the strangler window; the legacy `support-service` must be kept + running (but frozen) until host apps migrate. +- The legacy↔IIOS mapping must be consulted when porting features; this ADR is that map. +- `Notification` / `KnowledgeArticle` have no IIOS home yet — tracked as follow-ups, not blockers. + +## Alternatives considered + +- **Rename `support-service` in place** to the IIOS vocabulary. Rejected: high-risk migration + of a live service + DB for a system we intend to retire anyway; no benefit over greenfield. +- **Keep both vocabularies and bridge with adapters.** Rejected: perpetuates naming drift and + the KG-16 confusion indefinitely. +- **`@lynkeduppro/*` scope.** Rejected: all IIOS packages already ship under `@insignia`; + switching scopes now is churn with no upside. (A future rebrand can supersede this ADR.) diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..25f4840 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,19 @@ +# Architecture Decision Records (ADRs) + +This directory records the significant, hard-to-reverse decisions behind IIOS — +the *why*, not just the *what*. Code shows what we did; ADRs explain the choice so a +future contributor doesn't relitigate it or unknowingly violate it. + +## Convention + +- One file per decision: `NNNN-kebab-title.md` (zero-padded, monotonically increasing). +- Each ADR has: **Status**, **Context**, **Decision**, **Consequences**, and (where useful) + **Alternatives considered**. +- Status is one of `Proposed` · `Accepted` · `Superseded by ADR-XXXX` · `Deprecated`. +- ADRs are immutable once `Accepted`. To change a decision, write a new ADR that supersedes it. + +## Index + +| ADR | Title | Status | +|-----|-------|--------| +| [0001](0001-support-service-to-iios-naming-migration.md) | `support-service` → IIOS naming migration | Accepted |