@3030-labs/wotw 0.8.4
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 +312 -0
- package/LICENSE +36 -0
- package/LICENSE-NOTICES.md +199 -0
- package/README.md +147 -0
- package/SECURITY.md +181 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +14993 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/daemon/entry.d.ts +2 -0
- package/dist/daemon/entry.js +11544 -0
- package/dist/daemon/entry.js.map +1 -0
- package/dist/index.d.ts +617 -0
- package/dist/index.js +1290 -0
- package/dist/index.js.map +1 -0
- package/dist/wiki/templates/CLAUDE.md +87 -0
- package/dist/wiki/templates/getting-started.md +89 -0
- package/dist/wiki/templates/index.md +32 -0
- package/dist/wiki/templates/log.md +9 -0
- package/package.json +127 -0
- package/src/wiki/templates/CLAUDE.md +87 -0
- package/src/wiki/templates/getting-started.md +89 -0
- package/src/wiki/templates/index.md +32 -0
- package/src/wiki/templates/log.md +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# watcher-on-the-wall
|
|
2
|
+
|
|
3
|
+
> A local-first AI knowledge daemon. Drops files in, persistent wiki out.
|
|
4
|
+
> Every operation cryptographically signed. Served to any MCP-capable agent.
|
|
5
|
+
|
|
6
|
+
`wotw` is a small background process. You feed it raw notes, transcripts, and
|
|
7
|
+
documents; it writes you an interlinked Obsidian-compatible wiki, refreshes it
|
|
8
|
+
as your inputs change, and proves to you (and to auditors) exactly which model
|
|
9
|
+
wrote which page from which source at what cost.
|
|
10
|
+
|
|
11
|
+
It runs entirely on your machine. Your data never leaves unless you wire it
|
|
12
|
+
to a hosted LLM yourself (Anthropic, OpenAI, Gemini, or Ollama for fully
|
|
13
|
+
offline). Reads happen over MCP, so any agent that speaks Model Context
|
|
14
|
+
Protocol — Claude Code, Claude Desktop, Cursor — can query your wiki as a
|
|
15
|
+
memory tier.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g @3030-labs/wotw
|
|
21
|
+
wotw init # interactive: pick a vault, configure runtime
|
|
22
|
+
wotw start # daemon goes to the background
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Requires **Node.js ≥ 20**. macOS arm64 / amd64, Linux amd64, Windows amd64.
|
|
26
|
+
|
|
27
|
+
> **Run from source** (for contributors, or to run an unreleased change
|
|
28
|
+
> before it lands on npm):
|
|
29
|
+
>
|
|
30
|
+
> ```bash
|
|
31
|
+
> git clone https://github.com/3030-Labs/watcher-on-the-wall.git
|
|
32
|
+
> cd watcher-on-the-wall
|
|
33
|
+
> npm install # use npm, NOT pnpm — see note below
|
|
34
|
+
> npm run build
|
|
35
|
+
> npm install -g . # global install from the local checkout
|
|
36
|
+
> ```
|
|
37
|
+
>
|
|
38
|
+
> **Use `npm`, not `pnpm`, for a from-source install.** pnpm 10+ installs
|
|
39
|
+
> dependencies through a global content-addressable store and, with
|
|
40
|
+
> `pnpm link --global`, splits the dependency tree in a way that leaves
|
|
41
|
+
> native addons (`better-sqlite3`, the bundled `claude` binary) unreachable
|
|
42
|
+
> at runtime. `npm install -g .` avoids this entirely. (Tracked in
|
|
43
|
+
> `PASS-023-DOGFOOD-FINDINGS.md`.)
|
|
44
|
+
|
|
45
|
+
## 30-second quickstart
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
$ wotw init
|
|
49
|
+
┌ watcher-on-the-wall — setup wizard
|
|
50
|
+
│
|
|
51
|
+
◇ Where should your wiki live?
|
|
52
|
+
│ ~/Obsidian/research (detected)
|
|
53
|
+
│
|
|
54
|
+
◇ Which LLM runtime?
|
|
55
|
+
│ claude CLI (free with subscription)
|
|
56
|
+
│
|
|
57
|
+
│ Runtime ─ CLI mode (claude binary found at /usr/local/bin/claude)
|
|
58
|
+
│ Next steps ─
|
|
59
|
+
│ 1. Drop files in ~/Obsidian/research/raw/
|
|
60
|
+
│ 2. wotw start
|
|
61
|
+
│ 3. wotw candidates → wotw approve → pages land in wiki/
|
|
62
|
+
│
|
|
63
|
+
└ Done! Your wiki is ready.
|
|
64
|
+
|
|
65
|
+
$ wotw start
|
|
66
|
+
daemon running (pid 18412). logs: ~/.wotw/daemon.log
|
|
67
|
+
|
|
68
|
+
$ cp ~/Downloads/meeting-transcript.md ~/Obsidian/research/raw/
|
|
69
|
+
# daemon ingests it + synthesizes related concept pages into candidates/
|
|
70
|
+
|
|
71
|
+
$ wotw candidates # list pages awaiting review
|
|
72
|
+
$ wotw approve <page> # promote a candidate into wiki/
|
|
73
|
+
# (set ingestion.staging: false in wotw.yaml to auto-approve instead)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Generated pages land in `candidates/` first, not directly in `wiki/`.**
|
|
77
|
+
By default `wotw` stages every page for human review — run `wotw candidates`
|
|
78
|
+
to list them and `wotw approve <page>` to promote one into `wiki/`. Approval
|
|
79
|
+
appends a provenance record attributing the decision to you (`model=user`).
|
|
80
|
+
Set `ingestion.staging: false` in `wotw.yaml` to skip review and write
|
|
81
|
+
straight to `wiki/`.
|
|
82
|
+
|
|
83
|
+
Open the vault in Obsidian to see approved pages rendered as linked notes.
|
|
84
|
+
The daemon batches subsequent file drops, refreshes stale pages, and signs
|
|
85
|
+
every operation into a provenance chain you verify with `wotw audit`.
|
|
86
|
+
|
|
87
|
+
## What you get
|
|
88
|
+
|
|
89
|
+
- **Compounding wiki.** Drop a transcript, get categorized markdown with
|
|
90
|
+
YAML frontmatter, internal links, and a generated index. Drop ten more
|
|
91
|
+
on the same topic, get synthesis pages.
|
|
92
|
+
- **Provenance you can prove.** Every write — content + model + cost +
|
|
93
|
+
source — appended to a SHA-256 chain. `wotw audit` walks it and reports
|
|
94
|
+
tampering. Cryptographic attestation under tenant-managed keys (G5).
|
|
95
|
+
- **MCP-served.** Ten tools over streamable HTTP: search, query, define,
|
|
96
|
+
relate, cite_sources, query_progressive, query_facts, read_page, get_page,
|
|
97
|
+
list_pages. Bearer-token auth, per-IP rate limiting.
|
|
98
|
+
- **Local-first, BYOK.** Pick your provider (Anthropic / OpenAI / Gemini /
|
|
99
|
+
Ollama / claude CLI). Your Anthropic key never leaves your machine. The
|
|
100
|
+
wiki and its provenance chain are yours.
|
|
101
|
+
- **Token-efficient retrieval.** Context-efficiency Pass A + B ship
|
|
102
|
+
86-99% fewer tokens than naive query retrieval on benchmark fixtures.
|
|
103
|
+
Pure BM25, no embeddings.
|
|
104
|
+
- **Audit-ready.** Compliance Pack export (CT4.01) bundles your chain
|
|
105
|
+
with encrypted DEKs for offline verification via the separately
|
|
106
|
+
distributed [wotw-verify](https://github.com/3030-Labs/wotw-verify) Go
|
|
107
|
+
binary. Single statically-linked customer-side verifier, no daemon needed.
|
|
108
|
+
|
|
109
|
+
## Documentation
|
|
110
|
+
|
|
111
|
+
| | |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Up and running | [docs/init-walkthrough.md](docs/init-walkthrough.md) |
|
|
114
|
+
| Configuration knobs | [docs/configuration.md](docs/configuration.md) |
|
|
115
|
+
| CLI commands | [docs/cli-reference.md](docs/cli-reference.md) |
|
|
116
|
+
| MCP tools | [docs/mcp-tools.md](docs/mcp-tools.md) |
|
|
117
|
+
| Architecture | [docs/architecture.md](docs/architecture.md) |
|
|
118
|
+
| BYOK + LLM providers | [docs/self-hosted-byok.md](docs/self-hosted-byok.md) |
|
|
119
|
+
| Fact extraction gating | [docs/llm-provider-auto-resolution.md](docs/llm-provider-auto-resolution.md) |
|
|
120
|
+
| Provenance chain format | [docs/provenance.md](docs/provenance.md) |
|
|
121
|
+
| Compliance Pack wire format | [docs/pack-format-daemon.md](docs/pack-format-daemon.md) |
|
|
122
|
+
| Knowledge health + auto-heal | [docs/knowledge-health.md](docs/knowledge-health.md) |
|
|
123
|
+
| Obsidian integration | [docs/obsidian-setup.md](docs/obsidian-setup.md) |
|
|
124
|
+
| Multi-user + per-tenant tokens | [docs/multi-user.md](docs/multi-user.md) |
|
|
125
|
+
| Retrieval design (BM25 rationale) | [docs/retrieval-hardening.md](docs/retrieval-hardening.md) |
|
|
126
|
+
| Opt-in telemetry | [docs/telemetry.md](docs/telemetry.md) |
|
|
127
|
+
|
|
128
|
+
## Project status
|
|
129
|
+
|
|
130
|
+
`wotw` is pre-1.0. The substrate (ingestion, provenance, MCP, Compliance
|
|
131
|
+
Pack format) is stable and exercised by 900+ tests across 7 build gates;
|
|
132
|
+
the npm package is `@3030-labs/wotw`. Breaking changes are possible at
|
|
133
|
+
minor-version bumps until 1.0; see [CHANGELOG.md](CHANGELOG.md).
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
[AGPL-3.0-or-later](LICENSE) — see [LICENSE-NOTICES.md](LICENSE-NOTICES.md)
|
|
138
|
+
for the plain-English summary (what counts as a derivative work, how a
|
|
139
|
+
service offering must comply, what competitors can fork).
|
|
140
|
+
|
|
141
|
+
## Links
|
|
142
|
+
|
|
143
|
+
- Reporting a vulnerability: [SECURITY.md](SECURITY.md)
|
|
144
|
+
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
145
|
+
- Verifier binary: [3030-Labs/wotw-verify](https://github.com/3030-Labs/wotw-verify)
|
|
146
|
+
- Marketing + docs site: [wotw.dev](https://wotw.dev)
|
|
147
|
+
- Maintainer: [3030 Labs LLC](https://3030labs.io)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
`wotw` is pre-1.0. Only the latest minor version receives security
|
|
6
|
+
fixes. We do not backport to older minors; if a CVE lands, expect a
|
|
7
|
+
patch release on the current minor and an upgrade prompt.
|
|
8
|
+
|
|
9
|
+
| Version | Supported |
|
|
10
|
+
|----|----|
|
|
11
|
+
| 0.8.x | ✅ (current) |
|
|
12
|
+
| < 0.8 | ❌ |
|
|
13
|
+
|
|
14
|
+
## Reporting a vulnerability
|
|
15
|
+
|
|
16
|
+
**Do not open a public GitHub issue.** Public-issue disclosure puts
|
|
17
|
+
existing users at risk before they can patch.
|
|
18
|
+
|
|
19
|
+
Email `security@3030labs.io` with:
|
|
20
|
+
|
|
21
|
+
- A clear description of the vulnerability and the threat it enables
|
|
22
|
+
- Reproduction steps or a proof of concept (a minimal `wotw.config.yaml`
|
|
23
|
+
+ the exact command sequence is usually enough)
|
|
24
|
+
- The commit SHA (`git rev-parse HEAD`) or version tag (`wotw --version`)
|
|
25
|
+
you tested against
|
|
26
|
+
- The platform (OS + arch + Node version)
|
|
27
|
+
- Your disclosure timeline preferences (default: coordinated 30 days)
|
|
28
|
+
- Whether you'd like attribution in the release notes (default: yes,
|
|
29
|
+
with a name + optional link of your choosing)
|
|
30
|
+
|
|
31
|
+
You may PGP-encrypt the report. Our key is published at
|
|
32
|
+
[wotw.dev/keys/security.asc](https://wotw.dev/keys/security.asc) (or in
|
|
33
|
+
`scripts/security-pgp-key.asc` if pinned to a commit).
|
|
34
|
+
|
|
35
|
+
## Response SLA
|
|
36
|
+
|
|
37
|
+
We commit to the following timeline for any report received at
|
|
38
|
+
`security@3030labs.io`:
|
|
39
|
+
|
|
40
|
+
| Phase | Target |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Initial acknowledgment ("we received it, here is the tracking ID") | **5 business days** |
|
|
43
|
+
| Triage decision (in scope / out of scope, severity assigned) | **10 business days** |
|
|
44
|
+
| Fix shipped OR coordinated public disclosure | **30 calendar days** for high/critical; **90 days** for low/moderate |
|
|
45
|
+
| Credit + post-mortem in release notes | At publish of the fix release |
|
|
46
|
+
|
|
47
|
+
If we miss any of these targets, the reporter is welcome to publish
|
|
48
|
+
their findings. We will not pursue legal action against good-faith
|
|
49
|
+
research that follows this policy (see safe harbor below).
|
|
50
|
+
|
|
51
|
+
## Safe harbor for security researchers
|
|
52
|
+
|
|
53
|
+
3030 Labs LLC will NOT pursue legal action against security researchers
|
|
54
|
+
who, in good faith, report vulnerabilities to `security@3030labs.io`
|
|
55
|
+
under the following conditions:
|
|
56
|
+
|
|
57
|
+
1. **Scope discipline.** Testing is limited to `wotw` daemon code,
|
|
58
|
+
official `@3030-labs/wotw` npm artifacts, the `3030-Labs/wotw-verify`
|
|
59
|
+
binary, and infrastructure you control (your own laptop, your own
|
|
60
|
+
VMs). Testing against **other people's hosted wotw deployments,
|
|
61
|
+
3030 Labs' production infrastructure, or `wotw-cloud` tenants you
|
|
62
|
+
are not authorized for** is out of scope and not covered.
|
|
63
|
+
2. **No data exfiltration beyond proof-of-concept.** If your PoC needs
|
|
64
|
+
to demonstrate that data is reachable, fetch one record and stop.
|
|
65
|
+
Do not exfiltrate, retain, or redistribute another user's wiki
|
|
66
|
+
contents, provenance records, tokens, or LLM keys.
|
|
67
|
+
3. **No denial-of-service.** Rate-limit bypass demonstrations should
|
|
68
|
+
stop at the smallest input that proves the bypass. Don't drive
|
|
69
|
+
anyone's machine into a hot loop.
|
|
70
|
+
4. **Coordinated disclosure timeline.** Hold publication for the SLA
|
|
71
|
+
window above (or until we ship a fix, whichever is sooner) unless
|
|
72
|
+
we miss a SLA target. We will tell you up front if a fix needs more
|
|
73
|
+
than 30 days and explain why.
|
|
74
|
+
5. **No social engineering.** Reports targeting 3030 Labs personnel,
|
|
75
|
+
contractors, or users via phishing / pretexting are out of scope.
|
|
76
|
+
6. **Compliance with applicable law.** Safe harbor is contingent on
|
|
77
|
+
the research being legal in your jurisdiction. We can't waive the
|
|
78
|
+
CFAA on a foreign researcher's behalf, but we can confirm that
|
|
79
|
+
testing you do against your own machine, on your own data, with
|
|
80
|
+
no production-infra interaction, is something we authorize.
|
|
81
|
+
|
|
82
|
+
If you're uncertain whether a test plan falls inside safe harbor, ask
|
|
83
|
+
us first at `security@3030labs.io` and we'll tell you in writing.
|
|
84
|
+
|
|
85
|
+
## Bug bounty
|
|
86
|
+
|
|
87
|
+
We do not currently run a paid bounty. We will credit researchers in
|
|
88
|
+
release notes and at `wotw.dev/security/researchers` (once that page
|
|
89
|
+
exists). If you'd like a written reference letter for a portfolio,
|
|
90
|
+
we'll provide one for any in-scope finding rated moderate or higher.
|
|
91
|
+
|
|
92
|
+
## In scope
|
|
93
|
+
|
|
94
|
+
The following are considered in-scope for `wotw`:
|
|
95
|
+
|
|
96
|
+
- **Provenance chain integrity.** Any path that would let a malicious
|
|
97
|
+
actor tamper with past records without breaking the chain hash is a
|
|
98
|
+
critical bug.
|
|
99
|
+
- **Wiki path traversal.** Every MCP tool and every ingestion write
|
|
100
|
+
must refuse paths that escape `wiki_root`. The canonical check is
|
|
101
|
+
in `src/server/tools.ts::resolveWikiPath` — bypasses are critical.
|
|
102
|
+
- **Authentication bypass.** Any way to reach an authenticated MCP
|
|
103
|
+
endpoint without a valid bearer token.
|
|
104
|
+
- **Cost-budget bypass.** Any way to drive the daemon to spend beyond
|
|
105
|
+
`cost.max_daily_usd`, `cost.max_per_ingest_usd`, or
|
|
106
|
+
`cost.max_per_query_usd`.
|
|
107
|
+
- **Secret leakage.** API keys, bearer tokens, or user-provided paths
|
|
108
|
+
appearing in log output are a bug. The sanitizer at
|
|
109
|
+
`src/utils/sanitize.ts` is the only place these should be scrubbed;
|
|
110
|
+
if you find log output that bypasses it, please report it.
|
|
111
|
+
- **Race conditions in durable writes.** The wiki store and the
|
|
112
|
+
multi-user token store use temp-file + rename (`atomicWrite`); the
|
|
113
|
+
cost log, provenance chain, and dead-letter queue are append-only
|
|
114
|
+
JSONL files written with `appendFile` (POSIX `O_APPEND`) under a
|
|
115
|
+
single-writer mutex. Any window where a crash could leave corrupt
|
|
116
|
+
state — torn line, half-renamed temp, missed `fsync` — is in scope.
|
|
117
|
+
- **Multi-user isolation.** In multi-user mode, one tenant reading or
|
|
118
|
+
writing another tenant's wiki is critical.
|
|
119
|
+
|
|
120
|
+
## Out of scope
|
|
121
|
+
|
|
122
|
+
- **DoS via huge input files.** Dropping a 1 TB file into `raw/` will
|
|
123
|
+
use a lot of disk. That's expected behavior. We size-guard large
|
|
124
|
+
files at the ingestion boundary but we don't try to stop an operator
|
|
125
|
+
from filling their own disk.
|
|
126
|
+
- **Compromise of the underlying Anthropic/Claude service.** If Claude
|
|
127
|
+
gets prompted into writing a malicious page, that's a prompt
|
|
128
|
+
engineering concern, not a `wotw` security bug. (We do welcome PRs
|
|
129
|
+
that harden the ingestion prompts against injection.)
|
|
130
|
+
- **Misconfiguration.** If you leave `server.auth_token` unset and
|
|
131
|
+
expose the daemon to the internet on a non-loopback bind, you will
|
|
132
|
+
get warnings at startup and eventually a hard refusal to start (see
|
|
133
|
+
the no-auth safety rail in `src/server/index.ts`). That is not a
|
|
134
|
+
vulnerability — it's operator error.
|
|
135
|
+
- **Issues in bundled dependencies** with no exploitable path in
|
|
136
|
+
`wotw`. Please report those directly upstream.
|
|
137
|
+
|
|
138
|
+
## Deployment hardening checklist
|
|
139
|
+
|
|
140
|
+
If you're running `wotw` in anything that isn't a personal dev
|
|
141
|
+
machine, do all of these:
|
|
142
|
+
|
|
143
|
+
1. **Set `server.auth_token`** or enable `multi_user.enabled` with
|
|
144
|
+
per-user tokens (`wotw user add`). The daemon refuses to start on
|
|
145
|
+
a non-loopback bind without one of these configured.
|
|
146
|
+
2. **Bind to loopback** unless you're fronting it with a reverse proxy
|
|
147
|
+
that terminates TLS and does auth. The default is `127.0.0.1`.
|
|
148
|
+
3. **Set `provenance.verify_on_startup: true`** so a corrupt chain
|
|
149
|
+
halts the daemon instead of letting it continue writing on top of
|
|
150
|
+
bad state.
|
|
151
|
+
4. **Configure `cost.max_daily_usd`** to a value you're genuinely
|
|
152
|
+
willing to lose in a bad day. The default of `10.0` is not "free."
|
|
153
|
+
5. **Enable the dead-letter queue** (`ingestion.dead_letter_file`) and
|
|
154
|
+
monitor `wotw status` — a growing count of failed batches is
|
|
155
|
+
usually the first sign that something upstream is wrong.
|
|
156
|
+
6. **Don't commit `wotw.config.yaml` with secrets.** Keep
|
|
157
|
+
`ANTHROPIC_API_KEY` and `server.auth_token` in your shell
|
|
158
|
+
environment or a `.env` file that's gitignored.
|
|
159
|
+
7. **Back up `provenance-chain.jsonl` and the wiki git repo.** The
|
|
160
|
+
chain is your compliance artifact; losing it means losing your
|
|
161
|
+
audit trail.
|
|
162
|
+
8. **Rotate bearer tokens on personnel changes.** `wotw user revoke
|
|
163
|
+
<name>` is the supported path. In single-token mode, rewrite
|
|
164
|
+
`server.auth_token` and restart.
|
|
165
|
+
|
|
166
|
+
## Cryptographic details
|
|
167
|
+
|
|
168
|
+
- **Hashing.** SHA-256 over canonical JSON (recursively sorted keys,
|
|
169
|
+
no whitespace). Implementation: `src/provenance/hash.ts`.
|
|
170
|
+
- **Chain.** Forward-folding: `chain_hash = sha256(previous_chain_hash
|
|
171
|
+
|| id)`. Genesis is `"0".repeat(64)`.
|
|
172
|
+
- **Signature scheme.** Currently none — the chain is tamper-evident,
|
|
173
|
+
not tamper-proof. External signing (Sigstore / PGP / minisign) is on
|
|
174
|
+
the roadmap.
|
|
175
|
+
- **Token storage.** Multi-user tokens are stored verbatim in
|
|
176
|
+
`workspaces_dir/tokens.json` (mode `0600`, owner-only read/write).
|
|
177
|
+
Tokens are 256-bit (`wotw_` + 64 hex chars) generated by
|
|
178
|
+
`crypto.randomBytes`, so the on-disk file is the only credential
|
|
179
|
+
material and must be treated as secret. Backup tooling, container
|
|
180
|
+
image layers, and log shipping must all exclude it. A leaked
|
|
181
|
+
`tokens.json` requires `wotw user revoke` for every affected user.
|