@jungjaehoon/mama-os 0.19.0 → 0.19.1
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.
- package/CHANGELOG.md +12 -0
- package/README.md +52 -52
- package/dist/api/entity-audit-handler.d.ts +13 -0
- package/dist/api/entity-audit-handler.d.ts.map +1 -0
- package/dist/api/entity-audit-handler.js +124 -0
- package/dist/api/entity-audit-handler.js.map +1 -0
- package/dist/api/entity-audit-queue.d.ts +74 -0
- package/dist/api/entity-audit-queue.d.ts.map +1 -0
- package/dist/api/entity-audit-queue.js +123 -0
- package/dist/api/entity-audit-queue.js.map +1 -0
- package/dist/api/entity-audit-runner.d.ts +9 -0
- package/dist/api/entity-audit-runner.d.ts.map +1 -0
- package/dist/api/entity-audit-runner.js +240 -0
- package/dist/api/entity-audit-runner.js.map +1 -0
- package/dist/api/entity-review-handler.d.ts +18 -0
- package/dist/api/entity-review-handler.d.ts.map +1 -0
- package/dist/api/entity-review-handler.js +521 -0
- package/dist/api/entity-review-handler.js.map +1 -0
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +148 -0
- package/dist/api/graph-api.js.map +1 -1
- package/dist/auth/claude-code-auth.d.ts +12 -0
- package/dist/auth/claude-code-auth.d.ts.map +1 -0
- package/dist/auth/claude-code-auth.js +85 -0
- package/dist/auth/claude-code-auth.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +3 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +12 -6
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +13 -10
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +22 -27
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +48 -29
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/runtime/connector-init.d.ts.map +1 -1
- package/dist/cli/runtime/connector-init.js +22 -7
- package/dist/cli/runtime/connector-init.js.map +1 -1
- package/dist/connectors/kagemusha/index.d.ts.map +1 -1
- package/dist/connectors/kagemusha/index.js +4 -0
- package/dist/connectors/kagemusha/index.js.map +1 -1
- package/dist/memory/history-extractor.d.ts +24 -0
- package/dist/memory/history-extractor.d.ts.map +1 -1
- package/dist/memory/history-extractor.js +93 -1
- package/dist/memory/history-extractor.js.map +1 -1
- package/package.json +2 -2
- package/public/viewer/js/modules/entity-audit.js +106 -0
- package/public/viewer/js/modules/entity-review.js +66 -0
- package/public/viewer/src/modules/entity-audit.ts +154 -0
- package/public/viewer/src/modules/entity-review.ts +175 -0
- package/scripts/postinstall.js +58 -9
- package/templates/entity-audit-fixtures/cross-language-aliases.json +28 -0
- package/templates/entity-audit-fixtures/gold-canonical-identities.json +46 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.19.1] - 2026-04-20
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Claude Code auth detection** — install, init, setup, run, and status flows now prefer `claude auth status` when detecting whether Claude Code is logged in, avoiding false "auth missing" warnings on newer CLI installs that do not persist `~/.claude/.credentials.json`
|
|
15
|
+
- **Legacy auth fallback preserved** — older environments that still rely on `~/.claude/.credentials.json` continue to work as a fallback instead of breaking setup or status checks
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **Postinstall guidance** — postinstall now distinguishes between "Claude CLI missing" and "Claude CLI installed but logged out", and shows `claude auth login` when re-authentication is the real fix
|
|
20
|
+
- **Operator docs alignment** — standalone setup/troubleshooting/commands docs now describe the shipped Claude Code login flow and generated artifact expectations
|
|
21
|
+
|
|
10
22
|
## [0.10.2] - 2026-02-22
|
|
11
23
|
|
|
12
24
|
### Added
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Your knowledge is everywhere — Slack threads, email chains, code reviews, meeting notes, spreadsheets, Telegram messages. No human can track all of it. Important decisions get buried. Context gets lost between tools. When you need to make a decision, the information that would help is scattered across ten different apps and three months of history.
|
|
8
8
|
|
|
9
|
-
This isn't a memory problem. It's an intelligence problem. You don't just need to
|
|
9
|
+
This isn't a memory problem. It's an intelligence problem. You don't just need to _store_ information — you need something that reads everything, connects the dots, identifies what matters, and tells you what you're missing.
|
|
10
10
|
|
|
11
11
|
## What MAMA OS Does
|
|
12
12
|
|
|
@@ -62,7 +62,7 @@ See the full [Security Guide](../../docs/guides/security.md) for Cloudflare Zero
|
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
64
|
# 1. Authenticate a backend CLI (one-time)
|
|
65
|
-
claude
|
|
65
|
+
claude auth login # or: codex login
|
|
66
66
|
|
|
67
67
|
# 2. Install and start
|
|
68
68
|
npx @jungjaehoon/mama-os init
|
|
@@ -72,7 +72,7 @@ mama start
|
|
|
72
72
|
open http://localhost:3847
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
**Prerequisites:** Node.js >=
|
|
75
|
+
**Prerequisites:** Node.js >= 22.13.0, one authenticated backend CLI (Claude or Codex), 500MB disk space.
|
|
76
76
|
|
|
77
77
|
## Connectors (15)
|
|
78
78
|
|
|
@@ -83,22 +83,22 @@ mama connector add slack # Activate + auth guide
|
|
|
83
83
|
mama connector list # Status of all connectors
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
| Connector
|
|
87
|
-
|
|
88
|
-
| **Slack**
|
|
89
|
-
| **Discord**
|
|
90
|
-
| **Telegram**
|
|
91
|
-
| **Chatwork**
|
|
92
|
-
| **iMessage**
|
|
93
|
-
| **Gmail**
|
|
94
|
-
| **Calendar**
|
|
95
|
-
| **Drive**
|
|
96
|
-
| **Sheets**
|
|
97
|
-
| **Notion**
|
|
98
|
-
| **Obsidian**
|
|
99
|
-
| **Trello**
|
|
100
|
-
| **Kagemusha**
|
|
101
|
-
| **Claude Code** | Claude Code plugin installed
|
|
86
|
+
| Connector | Prerequisites | Config |
|
|
87
|
+
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
88
|
+
| **Slack** | Bot Token (api.slack.com → OAuth scopes) | `bot_token`, `app_token` |
|
|
89
|
+
| **Discord** | Bot Token (discord.com/developers → MESSAGE CONTENT INTENT) | `token`, `default_channel_id` |
|
|
90
|
+
| **Telegram** | Bot Token (@BotFather) | `token`, `allowed_chat_ids` |
|
|
91
|
+
| **Chatwork** | API Token (account settings) | `api_token`, `room_ids` |
|
|
92
|
+
| **iMessage** | macOS only (reads local chat.db) | No config needed |
|
|
93
|
+
| **Gmail** | [gws CLI](https://github.com/nicholasgasior/gws) installed + Google OAuth | `gws` in PATH |
|
|
94
|
+
| **Calendar** | gws CLI installed + Google OAuth | `gws` in PATH |
|
|
95
|
+
| **Drive** | gws CLI installed + Google OAuth | `gws` in PATH |
|
|
96
|
+
| **Sheets** | gws CLI installed + Google OAuth | `gws` in PATH, `spreadsheet_ids` |
|
|
97
|
+
| **Notion** | Integration Token (notion.so/my-integrations) | `api_token`, `database_ids` |
|
|
98
|
+
| **Obsidian** | [Obsidian](https://obsidian.md) installed + [Obsidian Terminal](https://github.com/polyipseity/obsidian-terminal) plugin enabled | `vault_path` in config.yaml |
|
|
99
|
+
| **Trello** | API Key + Token (trello.com/app-key) | `api_key`, `token`, `board_ids` |
|
|
100
|
+
| **Kagemusha** | Kagemusha running locally | Reads `kagemusha.db` directly |
|
|
101
|
+
| **Claude Code** | Claude Code plugin installed | Automatic via hooks |
|
|
102
102
|
|
|
103
103
|
**Google Workspace connectors** (Gmail, Calendar, Drive, Sheets) require the [gws CLI](https://github.com/nicholasgasior/gws) — a Google Workspace command-line tool. Install it, run `gws auth` once for OAuth, then MAMA polls via CLI.
|
|
104
104
|
|
|
@@ -108,12 +108,12 @@ Each connector classifies its source (truth / hub / spoke / reference) for the 3
|
|
|
108
108
|
|
|
109
109
|
MAMA OS runs specialized agents for knowledge management — not coding (that's what Claude Code does natively).
|
|
110
110
|
|
|
111
|
-
| Agent
|
|
112
|
-
|
|
113
|
-
| **Conductor**
|
|
114
|
-
| **Dashboard Agent** | Generates project briefings from connected sources
|
|
115
|
-
| **Wiki Agent**
|
|
116
|
-
| **Memory Agent**
|
|
111
|
+
| Agent | Role | Requires |
|
|
112
|
+
| ------------------- | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
113
|
+
| **Conductor** | Orchestrates other agents, handles user chat | — |
|
|
114
|
+
| **Dashboard Agent** | Generates project briefings from connected sources | — |
|
|
115
|
+
| **Wiki Agent** | Compiles knowledge into Obsidian vault | [Obsidian](https://obsidian.md) + [Terminal plugin](https://github.com/polyipseity/obsidian-terminal) |
|
|
116
|
+
| **Memory Agent** | Extracts decisions from conversations automatically | — |
|
|
117
117
|
|
|
118
118
|
Agents delegate via `delegate()` with skill injection and automatic retry. Configure in `~/.mama/config.yaml`.
|
|
119
119
|
|
|
@@ -121,14 +121,14 @@ Agents delegate via `delegate()` with skill injection and automatic retry. Confi
|
|
|
121
121
|
|
|
122
122
|
Web UI at `http://localhost:3847`. PWA-enabled for mobile (add to home screen).
|
|
123
123
|
|
|
124
|
-
| Tab
|
|
125
|
-
|
|
126
|
-
| **Dashboard** | Agent activity, memory stats, system health
|
|
127
|
-
| **Feed**
|
|
128
|
-
| **Wiki**
|
|
129
|
-
| **Memory**
|
|
130
|
-
| **Logs**
|
|
131
|
-
| **Settings**
|
|
124
|
+
| Tab | What it shows |
|
|
125
|
+
| ------------- | ---------------------------------------------------------- |
|
|
126
|
+
| **Dashboard** | Agent activity, memory stats, system health |
|
|
127
|
+
| **Feed** | Real-time stream from all connected sources |
|
|
128
|
+
| **Wiki** | Knowledge base (syncs with Obsidian vault) |
|
|
129
|
+
| **Memory** | Interactive reasoning graph (1000+ nodes), search, export |
|
|
130
|
+
| **Logs** | Daemon logs with filtering, pinning, stats, WebSocket mode |
|
|
131
|
+
| **Settings** | Connectors, gateways, agents, cron, token budget |
|
|
132
132
|
|
|
133
133
|
Floating chat panel on every tab — voice input, TTS, slash commands.
|
|
134
134
|
|
|
@@ -157,32 +157,32 @@ Slack, Gmail, Sheets... Discord, Slack, Telegram, Chatwork
|
|
|
157
157
|
|
|
158
158
|
## CLI
|
|
159
159
|
|
|
160
|
-
| Command
|
|
161
|
-
|
|
162
|
-
| `mama init`
|
|
163
|
-
| `mama setup`
|
|
164
|
-
| `mama start`
|
|
165
|
-
| `mama stop`
|
|
166
|
-
| `mama status`
|
|
167
|
-
| `mama connector <add\|remove\|list\|status>` | Manage connectors
|
|
160
|
+
| Command | Description |
|
|
161
|
+
| -------------------------------------------- | ------------------------ |
|
|
162
|
+
| `mama init` | Initialize workspace |
|
|
163
|
+
| `mama setup` | Interactive setup wizard |
|
|
164
|
+
| `mama start` | Start daemon |
|
|
165
|
+
| `mama stop` | Stop daemon |
|
|
166
|
+
| `mama status` | Check status |
|
|
167
|
+
| `mama connector <add\|remove\|list\|status>` | Manage connectors |
|
|
168
168
|
|
|
169
169
|
## Configuration
|
|
170
170
|
|
|
171
171
|
Main config: `~/.mama/config.yaml`
|
|
172
172
|
|
|
173
|
-
| Variable
|
|
174
|
-
|
|
175
|
-
| `MAMA_DB_PATH`
|
|
176
|
-
| `MAMA_HTTP_PORT` | `3847`
|
|
177
|
-
| `MAMA_WORKSPACE` | `~/.mama/workspace`
|
|
173
|
+
| Variable | Default |
|
|
174
|
+
| ---------------- | ------------------------ |
|
|
175
|
+
| `MAMA_DB_PATH` | `~/.mama/mama-memory.db` |
|
|
176
|
+
| `MAMA_HTTP_PORT` | `3847` |
|
|
177
|
+
| `MAMA_WORKSPACE` | `~/.mama/workspace` |
|
|
178
178
|
|
|
179
179
|
## Related Packages
|
|
180
180
|
|
|
181
|
-
| Package
|
|
182
|
-
|
|
183
|
-
| **@jungjaehoon/mama-os**
|
|
184
|
-
| **@jungjaehoon/mama-server** | MCP server for Claude Desktop
|
|
185
|
-
| **@jungjaehoon/mama-core**
|
|
181
|
+
| Package | Purpose |
|
|
182
|
+
| ---------------------------- | ----------------------------------- |
|
|
183
|
+
| **@jungjaehoon/mama-os** | Always-on AI runtime (this package) |
|
|
184
|
+
| **@jungjaehoon/mama-server** | MCP server for Claude Desktop |
|
|
185
|
+
| **@jungjaehoon/mama-core** | Shared memory engine |
|
|
186
186
|
|
|
187
187
|
## Development
|
|
188
188
|
|
|
@@ -202,4 +202,4 @@ MIT
|
|
|
202
202
|
|
|
203
203
|
---
|
|
204
204
|
|
|
205
|
-
**Last Updated:** 2026-04-
|
|
205
|
+
**Last Updated:** 2026-04-20
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { EntityAuditRunQueue, type EntityAuditQueueAdapter } from './entity-audit-queue.js';
|
|
3
|
+
export interface EntityAuditHandlerDeps {
|
|
4
|
+
queue: EntityAuditRunQueue;
|
|
5
|
+
runAuditInBackground?: (runId: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function createEntityAuditHandler(deps: EntityAuditHandlerDeps): {
|
|
8
|
+
handleStartAuditRun(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
9
|
+
handleListAuditRuns(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
10
|
+
handleGetAuditRun(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export declare function buildDefaultAuditHandlerDeps(adapter: EntityAuditQueueAdapter): EntityAuditHandlerDeps;
|
|
13
|
+
//# sourceMappingURL=entity-audit-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-audit-handler.d.ts","sourceRoot":"","sources":["../../src/api/entity-audit-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EAEL,mBAAmB,EACnB,KAAK,uBAAuB,EAC7B,MAAM,yBAAyB,CAAC;AAqDjC,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,mBAAmB,CAAC;IAC3B,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,sBAAsB;6BAElC,eAAe,OAAO,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;6BA2BpD,eAAe,OAAO,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;2BAOtD,eAAe,OAAO,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;EA6BpF;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,uBAAuB,GAC/B,sBAAsB,CAGxB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createEntityAuditHandler = createEntityAuditHandler;
|
|
4
|
+
exports.buildDefaultAuditHandlerDeps = buildDefaultAuditHandlerDeps;
|
|
5
|
+
const node_url_1 = require("node:url");
|
|
6
|
+
const entity_audit_queue_js_1 = require("./entity-audit-queue.js");
|
|
7
|
+
function json(res, status, body) {
|
|
8
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
9
|
+
res.end(JSON.stringify(body));
|
|
10
|
+
}
|
|
11
|
+
function parseUrl(req) {
|
|
12
|
+
return new node_url_1.URL(req.url ?? '/', 'http://localhost');
|
|
13
|
+
}
|
|
14
|
+
function parseRunIdFromPath(url) {
|
|
15
|
+
const parts = url.pathname.split('/').filter(Boolean);
|
|
16
|
+
const idx = parts.indexOf('runs');
|
|
17
|
+
if (idx < 0 || idx + 1 >= parts.length) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const id = parts[idx + 1];
|
|
21
|
+
return id ?? null;
|
|
22
|
+
}
|
|
23
|
+
async function readBody(req) {
|
|
24
|
+
const pre = req.body;
|
|
25
|
+
if (pre && typeof pre === 'object') {
|
|
26
|
+
return pre;
|
|
27
|
+
}
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
let data = '';
|
|
30
|
+
let size = 0;
|
|
31
|
+
req.on('data', (chunk) => {
|
|
32
|
+
size += chunk.length;
|
|
33
|
+
if (size > 1_048_576) {
|
|
34
|
+
req.destroy();
|
|
35
|
+
reject(new Error('Request body too large'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
data += chunk.toString('utf8');
|
|
39
|
+
});
|
|
40
|
+
req.on('end', () => {
|
|
41
|
+
if (!data) {
|
|
42
|
+
resolve({});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
resolve(JSON.parse(data));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
reject(new Error('Invalid JSON'));
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
req.on('error', reject);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function createEntityAuditHandler(deps) {
|
|
56
|
+
return {
|
|
57
|
+
async handleStartAuditRun(req, res) {
|
|
58
|
+
try {
|
|
59
|
+
await readBody(req);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
json(res, 400, {
|
|
63
|
+
error: {
|
|
64
|
+
code: 'entity.invalid_request',
|
|
65
|
+
message: err instanceof Error ? err.message : 'invalid body',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const { run_id } = deps.queue.enqueue();
|
|
72
|
+
if (deps.runAuditInBackground) {
|
|
73
|
+
deps.runAuditInBackground(run_id);
|
|
74
|
+
}
|
|
75
|
+
json(res, 202, { run_id });
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
if (err instanceof entity_audit_queue_js_1.AuditRunInProgressError) {
|
|
79
|
+
json(res, 409, err.toErrorEnvelope());
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
async handleListAuditRuns(req, res) {
|
|
86
|
+
const url = parseUrl(req);
|
|
87
|
+
const limit = Math.max(1, Math.min(200, Number(url.searchParams.get('limit') ?? 25) || 25));
|
|
88
|
+
const runs = deps.queue.list(limit);
|
|
89
|
+
json(res, 200, { runs });
|
|
90
|
+
},
|
|
91
|
+
async handleGetAuditRun(req, res) {
|
|
92
|
+
const url = parseUrl(req);
|
|
93
|
+
const runId = parseRunIdFromPath(url);
|
|
94
|
+
if (!runId) {
|
|
95
|
+
json(res, 400, {
|
|
96
|
+
error: { code: 'entity.invalid_request', message: 'missing run id' },
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const run = deps.queue.getStatus(runId);
|
|
101
|
+
if (!run) {
|
|
102
|
+
json(res, 404, {
|
|
103
|
+
error: { code: 'entity.audit_run_not_found', message: `run ${runId} not found` },
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
let metrics = null;
|
|
108
|
+
if (run.metric_summary_json) {
|
|
109
|
+
try {
|
|
110
|
+
metrics = JSON.parse(run.metric_summary_json);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
throw new Error(`Failed to parse entity audit metric_summary_json for run ${run.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
json(res, 200, { ...run, metrics });
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function buildDefaultAuditHandlerDeps(adapter) {
|
|
121
|
+
const queue = new entity_audit_queue_js_1.EntityAuditRunQueue({ adapter });
|
|
122
|
+
return { queue };
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=entity-audit-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-audit-handler.js","sourceRoot":"","sources":["../../src/api/entity-audit-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export type EntityAuditRunStatus = 'running' | 'complete' | 'failed' | 'timeout';
|
|
2
|
+
export interface EntityAuditQueueAdapter {
|
|
3
|
+
prepare(sql: string): {
|
|
4
|
+
run: (...params: unknown[]) => {
|
|
5
|
+
changes: number;
|
|
6
|
+
lastInsertRowid: number | bigint;
|
|
7
|
+
};
|
|
8
|
+
get: (...params: unknown[]) => unknown;
|
|
9
|
+
all: (...params: unknown[]) => unknown[];
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface EntityAuditRunSpec {
|
|
13
|
+
reason?: string;
|
|
14
|
+
baseline_run_id?: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface EntityAuditRunRow {
|
|
17
|
+
id: string;
|
|
18
|
+
status: EntityAuditRunStatus;
|
|
19
|
+
baseline_run_id: string | null;
|
|
20
|
+
classification: 'improved' | 'stable' | 'regressed' | 'inconclusive' | null;
|
|
21
|
+
metric_summary_json: string | null;
|
|
22
|
+
reason: string | null;
|
|
23
|
+
created_at: number;
|
|
24
|
+
completed_at: number | null;
|
|
25
|
+
}
|
|
26
|
+
export interface EntityAuditQueueOptions {
|
|
27
|
+
adapter: EntityAuditQueueAdapter;
|
|
28
|
+
timeBudgetMs?: number;
|
|
29
|
+
now?: () => number;
|
|
30
|
+
}
|
|
31
|
+
export declare const DEFAULT_AUDIT_TIME_BUDGET_MS: number;
|
|
32
|
+
export declare class AuditRunInProgressError extends Error {
|
|
33
|
+
readonly code = "entity.audit_run_in_progress";
|
|
34
|
+
readonly doc_section = "#audit-run-in-progress";
|
|
35
|
+
constructor();
|
|
36
|
+
toErrorEnvelope(): {
|
|
37
|
+
error: {
|
|
38
|
+
code: string;
|
|
39
|
+
message: string;
|
|
40
|
+
hint: string;
|
|
41
|
+
doc_url: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export declare class EntityAuditRunQueue {
|
|
46
|
+
private readonly adapter;
|
|
47
|
+
private readonly timeBudgetMs;
|
|
48
|
+
private readonly now;
|
|
49
|
+
constructor(opts: EntityAuditQueueOptions);
|
|
50
|
+
/**
|
|
51
|
+
* Insert a fresh `running` audit run. A second concurrent insert fails loudly
|
|
52
|
+
* via the migration 028 partial unique index and is surfaced as
|
|
53
|
+
* AuditRunInProgressError by this method.
|
|
54
|
+
*/
|
|
55
|
+
enqueue(spec?: EntityAuditRunSpec): {
|
|
56
|
+
run_id: string;
|
|
57
|
+
created_at: number;
|
|
58
|
+
};
|
|
59
|
+
getStatus(runId: string): EntityAuditRunRow | null;
|
|
60
|
+
list(limit?: number): EntityAuditRunRow[];
|
|
61
|
+
complete(runId: string, result: {
|
|
62
|
+
classification: 'improved' | 'stable' | 'regressed' | 'inconclusive';
|
|
63
|
+
metric_summary: unknown;
|
|
64
|
+
}): void;
|
|
65
|
+
fail(runId: string, reason: string): void;
|
|
66
|
+
markTimeout(runId: string, reason?: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* Called on boot. Any runs in `running` status survived a crash/restart and
|
|
69
|
+
* must be marked failed so the partial unique index does not remain held.
|
|
70
|
+
*/
|
|
71
|
+
recoverOrphans(reason?: string): number;
|
|
72
|
+
getTimeBudgetMs(): number;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=entity-audit-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-audit-queue.d.ts","sourceRoot":"","sources":["../../src/api/entity-audit-queue.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjF,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QACpB,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;QACrF,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;QACvC,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC;KAC1C,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,oBAAoB,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,GAAG,IAAI,CAAC;IAC5E,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,uBAAuB,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,4BAA4B,QAAgB,CAAC;AAE1D,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,kCAAkC;IAC/C,QAAQ,CAAC,WAAW,4BAA4B;;IAMhD,eAAe,IAAI;QACjB,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;KACzE;CAUF;AAwBD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,EAAE,uBAAuB;IAMzC;;;;OAIG;IACH,OAAO,CAAC,IAAI,GAAE,kBAAuB,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAoB9E,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAOlD,IAAI,CAAC,KAAK,SAAK,GAAG,iBAAiB,EAAE;IAOrC,QAAQ,CACN,KAAK,EAAE,MAAM,EACb,MAAM,EAAE;QACN,cAAc,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,cAAc,CAAC;QACrE,cAAc,EAAE,OAAO,CAAC;KACzB,GACA,IAAI;IAUP,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAUzC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAyB,GAAG,IAAI;IAUjE;;;OAGG;IACH,cAAc,CAAC,MAAM,SAAuB,GAAG,MAAM;IAWrD,eAAe,IAAI,MAAM;CAG1B"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EntityAuditRunQueue = exports.AuditRunInProgressError = exports.DEFAULT_AUDIT_TIME_BUDGET_MS = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
exports.DEFAULT_AUDIT_TIME_BUDGET_MS = 5 * 60 * 1000;
|
|
6
|
+
class AuditRunInProgressError extends Error {
|
|
7
|
+
code = 'entity.audit_run_in_progress';
|
|
8
|
+
doc_section = '#audit-run-in-progress';
|
|
9
|
+
constructor() {
|
|
10
|
+
super('Another entity audit run is already in progress.');
|
|
11
|
+
this.name = 'AuditRunInProgressError';
|
|
12
|
+
}
|
|
13
|
+
toErrorEnvelope() {
|
|
14
|
+
return {
|
|
15
|
+
error: {
|
|
16
|
+
code: this.code,
|
|
17
|
+
message: this.message,
|
|
18
|
+
hint: 'Wait for the current audit to finish, or inspect GET /api/entities/audit/runs.',
|
|
19
|
+
doc_url: `docs/operations/entity-substrate-runbook.md${this.doc_section}`,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.AuditRunInProgressError = AuditRunInProgressError;
|
|
25
|
+
function mapRow(row) {
|
|
26
|
+
return {
|
|
27
|
+
id: String(row.id),
|
|
28
|
+
status: row.status,
|
|
29
|
+
baseline_run_id: typeof row.baseline_run_id === 'string' ? row.baseline_run_id : null,
|
|
30
|
+
classification: typeof row.classification === 'string'
|
|
31
|
+
? row.classification
|
|
32
|
+
: null,
|
|
33
|
+
metric_summary_json: typeof row.metric_summary_json === 'string' ? row.metric_summary_json : null,
|
|
34
|
+
reason: typeof row.reason === 'string' ? row.reason : null,
|
|
35
|
+
created_at: Number(row.created_at),
|
|
36
|
+
completed_at: typeof row.completed_at === 'number'
|
|
37
|
+
? row.completed_at
|
|
38
|
+
: row.completed_at !== null && row.completed_at !== undefined
|
|
39
|
+
? Number(row.completed_at)
|
|
40
|
+
: null,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
class EntityAuditRunQueue {
|
|
44
|
+
adapter;
|
|
45
|
+
timeBudgetMs;
|
|
46
|
+
now;
|
|
47
|
+
constructor(opts) {
|
|
48
|
+
this.adapter = opts.adapter;
|
|
49
|
+
this.timeBudgetMs = opts.timeBudgetMs ?? exports.DEFAULT_AUDIT_TIME_BUDGET_MS;
|
|
50
|
+
this.now = opts.now ?? (() => Date.now());
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Insert a fresh `running` audit run. A second concurrent insert fails loudly
|
|
54
|
+
* via the migration 028 partial unique index and is surfaced as
|
|
55
|
+
* AuditRunInProgressError by this method.
|
|
56
|
+
*/
|
|
57
|
+
enqueue(spec = {}) {
|
|
58
|
+
const id = `audit_${(0, node_crypto_1.randomUUID)()}`;
|
|
59
|
+
const createdAt = this.now();
|
|
60
|
+
try {
|
|
61
|
+
this.adapter
|
|
62
|
+
.prepare(`INSERT INTO entity_audit_runs (id, status, baseline_run_id, reason, created_at)
|
|
63
|
+
VALUES (?, 'running', ?, ?, ?)`)
|
|
64
|
+
.run(id, spec.baseline_run_id ?? null, spec.reason ?? null, createdAt);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
+
if (message.includes('UNIQUE')) {
|
|
69
|
+
throw new AuditRunInProgressError();
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
return { run_id: id, created_at: createdAt };
|
|
74
|
+
}
|
|
75
|
+
getStatus(runId) {
|
|
76
|
+
const row = this.adapter.prepare(`SELECT * FROM entity_audit_runs WHERE id = ?`).get(runId);
|
|
77
|
+
return row ? mapRow(row) : null;
|
|
78
|
+
}
|
|
79
|
+
list(limit = 25) {
|
|
80
|
+
const rows = this.adapter
|
|
81
|
+
.prepare(`SELECT * FROM entity_audit_runs ORDER BY created_at DESC LIMIT ?`)
|
|
82
|
+
.all(limit);
|
|
83
|
+
return rows.map(mapRow);
|
|
84
|
+
}
|
|
85
|
+
complete(runId, result) {
|
|
86
|
+
this.adapter
|
|
87
|
+
.prepare(`UPDATE entity_audit_runs
|
|
88
|
+
SET status = 'complete', classification = ?, metric_summary_json = ?, completed_at = ?
|
|
89
|
+
WHERE id = ?`)
|
|
90
|
+
.run(result.classification, JSON.stringify(result.metric_summary), this.now(), runId);
|
|
91
|
+
}
|
|
92
|
+
fail(runId, reason) {
|
|
93
|
+
this.adapter
|
|
94
|
+
.prepare(`UPDATE entity_audit_runs
|
|
95
|
+
SET status = 'failed', reason = ?, completed_at = ?
|
|
96
|
+
WHERE id = ?`)
|
|
97
|
+
.run(reason, this.now(), runId);
|
|
98
|
+
}
|
|
99
|
+
markTimeout(runId, reason = 'time_budget_exceeded') {
|
|
100
|
+
this.adapter
|
|
101
|
+
.prepare(`UPDATE entity_audit_runs
|
|
102
|
+
SET status = 'timeout', reason = ?, completed_at = ?
|
|
103
|
+
WHERE id = ?`)
|
|
104
|
+
.run(reason, this.now(), runId);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Called on boot. Any runs in `running` status survived a crash/restart and
|
|
108
|
+
* must be marked failed so the partial unique index does not remain held.
|
|
109
|
+
*/
|
|
110
|
+
recoverOrphans(reason = 'standalone_restart') {
|
|
111
|
+
const res = this.adapter
|
|
112
|
+
.prepare(`UPDATE entity_audit_runs
|
|
113
|
+
SET status = 'failed', reason = ?, completed_at = ?
|
|
114
|
+
WHERE status = 'running'`)
|
|
115
|
+
.run(reason, this.now());
|
|
116
|
+
return Number(res.changes ?? 0);
|
|
117
|
+
}
|
|
118
|
+
getTimeBudgetMs() {
|
|
119
|
+
return this.timeBudgetMs;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.EntityAuditRunQueue = EntityAuditRunQueue;
|
|
123
|
+
//# sourceMappingURL=entity-audit-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-audit-queue.js","sourceRoot":"","sources":["../../src/api/entity-audit-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EntityAuditQueueAdapter, EntityAuditRunQueue } from './entity-audit-queue.js';
|
|
2
|
+
export declare function resolveEntityAuditFixturesPath(fixturesPath?: string): string;
|
|
3
|
+
export declare function runEntityAuditInBackground(args: {
|
|
4
|
+
queue: EntityAuditRunQueue;
|
|
5
|
+
adapter: EntityAuditQueueAdapter;
|
|
6
|
+
runId: string;
|
|
7
|
+
fixturesPath?: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=entity-audit-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-audit-runner.d.ts","sourceRoot":"","sources":["../../src/api/entity-audit-runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAuG5F,wBAAgB,8BAA8B,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAO5E;AAwND,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,KAAK,EAAE,mBAAmB,CAAC;IAC3B,OAAO,EAAE,uBAAuB,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoChB"}
|