# ICD Drift Audit — SDK vs Backend

**Date:** 2026-03-23
**Method:** Compared `src/js/sw/sdk/api-domains.js` against `docs/ICD/*.md` and `server/main.go`.
**Principle:** ICD is the zone of truth. SDK must conform to it.

---

## A. SDK Bugs — Wrong method or path (fix in SDK)

| SDK Method | SDK Calls | Backend Route | Issue |
|---|---|---|---|
| `workflows.update(id, data)` | `PUT /workflows/:id` | `PATCH /workflows/:id` | `crud()` generates PUT; backend is PATCH → 404/405 |
| `workspaces.update(id, data)` | `PUT /workspaces/:id` | `PATCH /workspaces/:id` | Same — `crud()` generates PUT; backend is PATCH |
| `tasks.start(id, data)` | `POST /tasks/:id/start` | `POST /tasks/:id/run` | Path mismatch → 404 |
| `tasks.stop(id)` | `POST /tasks/:id/stop` | `POST /tasks/:id/kill` | Path mismatch → 404 |
| `dataPortability.deleteAccount(data)` | `POST /profile/delete` | `DELETE /me` | Both method and path wrong |

## B. SDK Bug — Duplicate key overwrites (fix in SDK)

`notifications` is defined **three times** as a top-level key in the `createDomains` return object:

1. **Line 186** — Domain #11 (has `prefs`, `setPref`, `delPref`, uses `POST` for markRead)
2. **Line 431** — Inside `admin` namespace (correct, no conflict)
3. **Line 501** — "Misc" section (uses `PATCH` for markRead, no preference methods)

JavaScript last-write-wins: #3 overwrites #1. The notification preference methods (`prefs`, `setPref`, `delPref`) are silently lost. The `markRead` method changes from POST to PATCH (PATCH matches the ICD, so #3 has the correct HTTP method but is missing methods).

**Fix:** Delete the duplicate at line 501. Merge its `del` method and `PATCH` fix into the domain #11 block at line 186.

## C. ICD Gaps — Endpoints exist in main.go, not documented in ICD

These endpoints are real (registered in main.go, used by the SDK) but have no ICD documentation.

| Endpoint | Belongs in ICD File | Notes |
|---|---|---|
| `POST /channels/:id/mark-read` | channels.md | SDK: `channels.markRead()` |
| `POST /channels/:id/generate-title` | channels.md | SDK: `channels.generateTitle()` |
| `POST /channels/:id/summarize` | channels.md | SDK: `channels.summarize()` |
| `GET /channels/:id/messages/:msgId/siblings` | channels.md | SDK: `channels.siblings()` |
| `GET /knowledge-bases-discoverable` | knowledge.md | SDK: `knowledge.discoverable()` |
| `GET /folders`, `POST`, `PUT /:id`, `DELETE /:id` | (new section) | Full CRUD, needs own ICD section or add to channels.md |
| `GET /users/search?q=...` | (new section) | SDK: `users.search()` |
| `POST /presence/heartbeat`, `GET /presence` | (new section) | SDK: `presence.heartbeat()` |
| `GET /usage` | (new section) | SDK: `usage.mine()` |
| `GET /groups/mine` | (new section) | SDK: `groups.mine()` |
| `GET /export/me` | utility.md | SDK: `dataPortability.exportMe()` |
| `DELETE /me` | utility.md | GDPR account deletion |
| `GET /git-credentials`, `POST`, `DELETE /:id` | (new section) | SDK: `git.credentials.*` |
| `POST /git-credentials/generate` | (new section) | Not in SDK — SSH key generation |
| `GET /git-credentials/:id/public-key` | (new section) | Not in SDK |
| `GET /tools` | (new section) | SDK: `tools.list()` |

## D. ICD-Documented Endpoints Missing from SDK

In the ICD but the SDK doesn't expose them. Add only as surfaces need them.

| Endpoint | ICD File | Notes |
|---|---|---|
| Workflow stages CRUD (`GET/POST/PUT/DELETE /workflows/:id/stages/*`) | workflows.md | Workflow editor needs these |
| `PATCH /workflows/:id/stages/reorder` | workflows.md | |
| `POST /workflows/:id/publish` | workflows.md | Team-scoped version exists in SDK |
| `POST /workflows/:id/start` | workflows.md | Instance creation |
| `GET /channels/:id/workflow/status` | workflows.md | |
| `POST /channels/:id/workflow/advance` | workflows.md | |
| Workspace archive (`download`, `upload`) | workspaces.md | |
| `POST /workspaces/:id/reconcile` | workspaces.md | |
| `GET /workspaces/:id/stats` | workspaces.md | |
| `GET /workspaces/:id/index-status` | workspaces.md | |
| `POST /workspaces/:id/git/clone`, `git/pull` | workspaces.md | |
| `GET /extensions/:id/manifest` | extensions.md | |
| `GET /extensions/tools` | extensions.md | |
| `POST /personas/:id/avatar`, `DELETE` | personas.md | User-scoped (admin-scoped exists) |
| `POST /knowledge-bases/:id/rebuild` | knowledge.md | |

## E. Response Shape Mismatches

| Endpoint | Response Shape | Convention | Notes |
|---|---|---|---|
| `GET /api-configs` | `{"configs": [...]}` | Should be `{"data": [...]}` | SDK `_unwrap` won't strip |
| `GET /admin/configs` | `{"configs": [...]}` | Should be `{"data": [...]}` | Same |
| `GET /admin/models` | `{"models": [...]}` | Should be `{"data": [...]}` | Same |
| `GET /admin/users` | `{"users": [...]}` | Should be `{"data": [...]}` | Same |

These use named keys instead of the `{"data": [...]}` envelope convention. The SDK's `_unwrap` doesn't strip these, so consumers get the envelope object.

---

## Recommended Priority

1. Fix §A (SDK 404s) — these are broken in production
2. Fix §B (duplicate notifications key)
3. Document §C (ICD gaps) — endpoints work, just undocumented
4. Add §D methods to SDK — only as surfaces need them
5. Migrate §E response shapes to `{"data": [...]}` — breaking change, defer
