Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
75a4925
refactor(mcp): collect capability registrations as replayable thunks …
edtadros May 24, 2026
408439c
feat(mcp): Streamable HTTP transport — gnosys serve --transport http …
edtadros May 24, 2026
0dfa0a8
feat(docker): containerize the network-hosted MCP server (v5.12 Phase D)
edtadros May 24, 2026
f46a62a
feat(cli): gnosys centralize — seed a central server's brain from a l…
edtadros May 24, 2026
ed042a5
feat(cli): gnosys connect — point an IDE at a remote gnosys server (v…
edtadros May 24, 2026
e8a7ff4
fix(mcp): normalize tool error envelopes via formatMcpError
edtadros May 25, 2026
3680ecd
docs(readme): add complete MCP Tool Reference table (all 51 tools)
edtadros May 25, 2026
8b563bc
test(mcp): fuzz tool input schemas; guard main() for import-testability
edtadros May 25, 2026
0f4f958
test(mcp): verify HTTP registration replay across concurrent sessions
edtadros May 25, 2026
17546d5
feat(cli): add --json output to 7 read-only commands
edtadros May 25, 2026
271db10
fix(db): set busy_timeout on all file-based Database() opens
edtadros May 25, 2026
d4c8fc4
perf(db): index memories.modified and memories.created
edtadros May 25, 2026
b7981b9
test(db): add extended recovery cases (SIGKILL, ENOSPC, FTS, no binary)
edtadros May 25, 2026
d2531e0
test(lifecycle): end-to-end memory lifecycle with consistency assertions
edtadros May 25, 2026
a4c9fa7
test(lifecycle): per-op DB invariant test
edtadros May 25, 2026
d2345cd
test(search): fixture corpus + golden top-3 stability across variants
edtadros May 25, 2026
53d6698
docs(search): add search-modes.md comparing keyword/semantic/hybrid
edtadros May 25, 2026
a2006c6
fix(ask): harden synthesis prompt against embedded prompt injection
edtadros May 25, 2026
a353e32
docs(llm): document the LLMProvider interface contract
edtadros May 25, 2026
32c67da
fix(llm): enforce request timeouts on all provider calls
edtadros May 25, 2026
94e4ddf
fix(llm): format-agnostic API key redaction in provider errors
edtadros May 25, 2026
e707be2
fix(embeddings): one-line install hint when transformers is missing
edtadros May 25, 2026
52329da
docs(cost): document cost model and budget responsibility
edtadros May 25, 2026
81f15d6
test(ingest): adversarial fixture suite for ingestFile
edtadros May 25, 2026
7cbb97d
fix(ingest): guard DOCX extractor against zip bombs
edtadros May 25, 2026
8230fcc
test(ingest): lock chunkSplitter determinism
edtadros May 25, 2026
d9c105d
test(ingest): cover special-character file paths
edtadros May 25, 2026
82299ac
fix(webingest): close SSRF holes (redirect bypass, loopback, IP encod…
edtadros May 25, 2026
d276274
test(remote): two-machine sync simulation with no-data-loss assertions
edtadros May 25, 2026
f73d4b9
test(remote): push resume after interruption (no partial state, idemp…
edtadros May 25, 2026
30bf915
fix(machine): GNOSYS_MACHINE_ID override for stable id across hostnam…
edtadros May 25, 2026
52916b9
test(dream): abort mid-cycle + clean re-run resilience
edtadros May 25, 2026
f3eb11a
docs(setup): add first-run setup walkthrough
edtadros May 25, 2026
31f2d01
docs(config): document configuration precedence chains
edtadros May 25, 2026
bf53aab
feat(preferences): validate preference keys with did-you-mean hints
edtadros May 25, 2026
3826595
feat(config): atomic config writes (temp-then-rename)
edtadros May 25, 2026
d1020e3
fix(http): require auth token on non-loopback bind, refuse to start
edtadros May 25, 2026
ea8aecc
test(http): lock bearer-token contract (missing/wrong/correct → 401/4…
edtadros May 25, 2026
5bbe995
test(http): lock session-isolation property for concurrent sessions
edtadros May 25, 2026
281e043
fix(http): reap idle sessions to stop disconnect leaks
edtadros May 25, 2026
a3a584f
feat(http): default-deny browser origins (CORS Origin guard)
edtadros May 25, 2026
b09e645
docs(network-mcp): document rate-limiting rationale
edtadros May 25, 2026
0b73bd6
fix(http): bound request body size and receive-time (DoS hardening)
edtadros May 25, 2026
3d4fd9e
feat(audit): emit audit rows for remote push/pull (sync observability)
edtadros May 25, 2026
53f5d3f
refactor(history): remove legacy git-backed rollback/history (DB-only)
edtadros May 25, 2026
2d1f9e8
feat(provenance): surface source_file in reads + audit file ingestion
edtadros May 25, 2026
906f0a2
fix(db): migrate legacy schema before applying SCHEMA_SQL (v1/v2 upgr…
edtadros May 25, 2026
dae418c
feat(upgrade): detect package manager for gnosys upgrade
edtadros May 25, 2026
3dc9b63
fix(import): use safeFetch for import-from-URL (SSRF parity with 7.7)
edtadros May 25, 2026
b9c4cd1
feat(export): surface excluded-archived count (no silent drops)
edtadros May 25, 2026
da45fe4
test(ide): golden fixtures for per-IDE init rules block
edtadros May 25, 2026
07e1e04
fix(pkg): ship docs/logo.svg so the README logo renders on npm
edtadros May 25, 2026
401174f
docs(readme): state Node.js >= 18 prerequisite in Install
edtadros May 25, 2026
2175b97
fix(readme): drop removed gnosys_rollback from tool table
edtadros May 25, 2026
d0dab15
fix(npm): canonicalize repository.url for provenance
edtadros May 25, 2026
f518e53
feat(npm): add model-context-protocol + agent-memory keywords
edtadros May 25, 2026
d1ee0fe
fix(build): clean dist before build to stop shipping deleted modules
edtadros May 25, 2026
951270c
ci: test Node 18 & 20 so engines.node >=18 is honest
edtadros May 25, 2026
8343508
docs(readme): document both bins (gnosys + gnosys-mcp)
edtadros May 25, 2026
d41b014
docs(readme): document optional native deps with install hints
edtadros May 25, 2026
2d73838
fix(security): prevent path traversal in gnosys export (A.5)
edtadros May 26, 2026
35dbc64
fix(security): use argv arrays for cp/open to prevent shell injection…
edtadros May 26, 2026
7f1e07f
fix(security): create .env and gnosys.db with 0600 perms (A.11)
edtadros May 26, 2026
4ed82e6
docs(security): document update integrity (A.12)
edtadros May 26, 2026
77f1e43
docs(security): add threat model (A.13)
edtadros May 26, 2026
f353c98
chore(lint): adopt Biome as linter (B.2)
edtadros May 26, 2026
41a0451
refactor(deadcode): remove dead exports, declare jszip, add knip (B.3)
edtadros May 26, 2026
4525be2
refactor(deps): resolve circular dependencies (B.4)
edtadros May 26, 2026
5dabb48
test(coverage): measure dream.ts; record C.1 baseline
edtadros May 26, 2026
804483e
test: add unit tests for retry/progress/heartbeat/modelValidation (C.2)
edtadros May 26, 2026
f3a3994
test(isolation): stop resolver-routing writing to real ~/.config/gnos…
edtadros May 26, 2026
1cb82de
ci: run test matrix on Linux + macOS (C.7)
edtadros May 26, 2026
ea3f618
test(acceptance): smoke MCP/WebKB/sync at the acceptance layer (C.9)
edtadros May 26, 2026
83d7af3
feat(logging): structured logger (text/JSON/file sinks) (D.5)
edtadros May 26, 2026
34e936b
docs(changelog): backfill 5.4.1/5.4.3 + Historical versions note (E.2)
edtadros May 26, 2026
9bd309d
docs(mcp): generate docs/mcp-tools.md from src/index.ts (E.4)
edtadros May 26, 2026
7d02106
docs(cli): generate docs/cli.md from src/cli.ts (E.5)
edtadros May 26, 2026
8ea17f9
docs(adr): backfill 8 ADRs from Gnosys memory (E.6)
edtadros May 26, 2026
2714f47
docs: add source-of-truth content map (E.8)
edtadros May 26, 2026
7756bce
test(ingest): raise src/lib/ingest.ts coverage 17% → 100% (CC.1)
edtadros May 26, 2026
07fc6d8
test(dream): raise src/lib/dream.ts coverage 29% → 95% (CC.2)
edtadros May 26, 2026
40603ea
test(remote): raise src/lib/remote.ts coverage 74% → 80% (CC.3)
edtadros May 26, 2026
b8e88f0
test(db): raise src/lib/db.ts coverage 81% → 88% (CC.4)
edtadros May 26, 2026
68b93e2
docs: add coverage-baseline.md recording C.1 gate met (CC.5)
edtadros May 26, 2026
15179f7
docs(changelog): add ## [Unreleased] for 84 commits since v5.10.0 (RE…
edtadros May 26, 2026
1241f29
docs(security): add companion link to docs/threat-model.md (OPEN.1)
edtadros May 26, 2026
99470f8
docs(contrib): link docs/source-of-truth.md from CONTRIBUTING.md (OPE…
edtadros May 26, 2026
f63d137
build(publish): trim sourcemaps via tsconfig.publish.json (OPEN.3)
edtadros May 26, 2026
472d01d
refactor(logging): migrate 10 high-signal console.error sites to log.…
edtadros May 26, 2026
a1a71bf
docs(adr): backfill 4 ADRs (0009-0012) from Gnosys memory (OPEN.5)
edtadros May 26, 2026
ca707f7
fix(errors): enrich better-sqlite3 install hint at 6 sites (OPEN.6)
edtadros May 26, 2026
64a40a1
chore: release v5.11.0
edtadros May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@ on:

jobs:
build-and-test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
node-version: [22, 24]
os: [ubuntu-latest, macos-latest]
node-version: [20, 22, 24]
exclude:
# macOS Node 20 truncates `gnosys --help` mid-output when stdout is a
# pipe (Node 20.x macOS stdout-flush-on-exit quirk). Affects only
# piped capture; interactive use is fine. Track separately; re-enable
# once on Node 22+ or when the stdout-flush bug is patched upstream.
- os: macos-latest
node-version: 20

steps:
- uses: actions/checkout@v5
Expand All @@ -36,19 +45,19 @@ jobs:
run: npm test

- name: Run tests with coverage
if: matrix.node-version == 24
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24
run: npm run test:coverage

- name: Upload coverage report
if: matrix.node-version == 24
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24
uses: actions/upload-artifact@v5
with:
name: coverage-report
path: coverage/
retention-days: 14

- name: Check coverage thresholds
if: matrix.node-version == 24
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24
run: |
if [ -f coverage/coverage-summary.json ]; then
echo "Coverage summary:"
Expand All @@ -68,7 +77,7 @@ jobs:
# failures (new modules without tests dropping the global average
# under the 50% threshold).
- name: Check coverage of newly-added files
if: matrix.node-version == 24
if: matrix.os == 'ubuntu-latest' && matrix.node-version == 24
run: |
git fetch --depth=50 origin master:refs/remotes/origin/master 2>/dev/null || true
COVERAGE_BASE_REF=origin/master node scripts/check-new-file-coverage.mjs
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ coverage/
# Agent config, rules & skills (local-only — AGENTS.md stays public)
rules/
.gnosys/
CLAUDE.md
/CLAUDE.md
.claude/
.cursor/
.codex/

# Negate the CLAUDE.md ignore for this golden fixture (macOS case-insensitive FS)
!src/test/fixtures/ide-init/claude.md
6 changes: 6 additions & 0 deletions .madgerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"detectiveOptions": {
"ts": { "skipAsyncImports": true },
"es6": { "skipAsyncImports": true }
}
}
155 changes: 143 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,128 @@ All notable changes to Gnosys are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Historical versions

Detailed CHANGELOG coverage begins at **5.2.16**. Earlier 5.0.0–5.2.15 releases and a few 5.2.x patches without individual entries (5.2.17, 5.2.18, 5.2.21) are tracked via [git tags](https://github.com/proticom/gnosys/tags). Versions 5.2.13, 5.2.14, and 5.2.15 were CHANGELOG-only and never published to npm.

## [5.11.0] — 2026-05-26

Pending release — bundles 84 commits since 5.10.0 covering a network-hosted MCP
transport, a hardened HTTP surface, structured logging, a v5.12 portability
track, and the C/D/E hardening + documentation review.

### Added

- **Network-hosted MCP transport (v5.12 Phases A–E).** Run Gnosys as a remote
MCP server over Streamable HTTP, containerize it, and point local IDEs at it.
- `gnosys serve --transport http` — Streamable HTTP transport for network MCP
(v5.12 Phase A + C).
- Capability registrations collected as replayable thunks so HTTP sessions
replay the same tool surface as stdio (v5.12 Phase A foundation).
- `gnosys connect` — point an IDE at a remote Gnosys server (v5.12 Phase B).
- `gnosys centralize` — seed a central server's brain from a local one
(v5.12 Phase E).
- Docker support for the network-hosted MCP server (v5.12 Phase D).
- **Structured logging (D.5).** Text, JSON, and file sinks for operational
visibility across CLI and server modes.
- **Audit rows for remote sync.** Push/pull operations now emit audit rows for
sync observability.
- **HTTP CORS guard.** Default-deny browser origins on the HTTP transport.
- **Atomic config writes.** Config updates use temp-then-rename for crash safety.
- **Preference key validation.** Invalid preference keys get did-you-mean hints.
- **`--json` on read-only commands.** Seven read-only CLI commands now support
machine-readable output.
- **Provenance in reads.** `source_file` surfaced in reads; audit file ingestion
tracked.
- **Export transparency.** Excluded-archived count surfaced so exports do not
silently drop memories.
- **`gnosys upgrade` package-manager detection.** Upgrade command detects npm,
pnpm, or yarn automatically.
- **npm discoverability.** Added `model-context-protocol` and `agent-memory`
keywords to package.json.
- **Documentation and ADRs (E.4–E.8).**
- Generated `docs/cli.md` from `src/cli.ts` (E.5) and `docs/mcp-tools.md`
from `src/index.ts` (E.4).
- Backfilled 8 ADRs from Gnosys memory (E.6).
- `docs/source-of-truth.md` — content map for where docs live (E.8).
- `docs/threat-model.md` — security threat model (A.13).
- `docs/coverage-baseline.md` — C.1 coverage gate baseline (CC.5).
- Setup walkthrough, configuration precedence chains, LLM provider contract,
search-modes comparison, cost model, update-integrity notes, and network-MCP
rate-limiting rationale.
- **Acceptance smokes (C.9).** MCP, WebKB, and sync smoke tests at the
acceptance layer.
- **Test coverage expansion.** Extended suites for ingest (100% lines), dream
(95%), db (88%), remote (80%), HTTP session isolation, bearer-token contract,
MCP registration replay, search golden corpus, lifecycle invariants, DB
recovery, and adversarial ingest fixtures.

### Changed

- **CI test matrix on Linux + macOS (C.7).** Tests now run on both platforms.
- **Node 18 & 20 in CI.** Matrix expanded so `engines.node >=18` is verified.
- **Biome linter (B.2).** Adopted Biome as the project linter.
- **Dependency cleanup (B.3/B.4).** Removed dead exports, declared jszip,
added knip; resolved circular dependencies.
- **DB-only history (B.3).** Removed legacy git-backed rollback/history paths;
SQLite is the sole source of truth.
- **CHANGELOG backfill (E.2).** Added 5.4.1/5.4.3 entries and the Historical
versions preamble note.
- **README updates.** Slimmed and repositioned; documents both `gnosys` and
`gnosys-mcp` bins, Node.js >= 18 prerequisite, optional native deps with
install hints, and a complete MCP Tool Reference table (all 51 tools).
- **DB performance.** Indexed `memories.modified` and `memories.created`.

### Fixed

- **Path traversal in export (A.5).** `gnosys export` no longer allows
directory escape via crafted paths.
- **Shell injection (A.8).** `cp` and `open` subprocess calls use argv arrays
instead of shell strings.
- **File permissions (A.11).** `.env` and `gnosys.db` created with `0600`
permissions.
- **Clean build / clean dist (20.13).** `dist/` cleaned before build so deleted modules are
not shipped to npm.
- **Legacy schema migration.** DB migrates v1/v2 legacy schema before applying
current `SCHEMA_SQL`.
- **npm provenance.** Canonicalized `repository.url` for npm provenance.
- **README tool table.** Removed stale `gnosys_rollback` reference.
- **Package assets.** `docs/logo.svg` shipped so the README logo renders on npm.
- **MCP error envelopes.** Tool errors normalized via `formatMcpError`.
- **Machine ID stability.** `GNOSYS_MACHINE_ID` env override for stable id
across hostname changes.
- **DB busy timeout.** All file-based `Database()` opens set `busy_timeout`.
- **Embeddings install hint.** One-line hint when `@xenova/transformers` is
missing.
- **LLM request timeouts.** Enforced on all provider calls.
- **HTTP session cleanup.** Idle sessions reaped to stop disconnect leaks.

### Security

- **HTTP auth on non-loopback bind.** Server refuses to start without an auth
token when bound beyond loopback; bearer-token contract locked by tests.
- **HTTP DoS hardening.** Request body size bounded; receive-time limits
enforced.
- **SSRF parity (17.4).** `safeFetch` used for import-from-URL; web ingest
closes redirect bypass, loopback, and IP-encoding holes.
- **DOCX zip-bomb guard.** DOCX extractor rejects archives that exceed safe
size limits.
- **API key redaction.** Format-agnostic redaction in LLM provider error
messages.
- **Prompt injection hardening.** Synthesis prompt in `gnosys ask` hardened
against embedded prompt injection.
- **CORS default-deny.** Browser origins blocked unless explicitly allowed
(also listed under Added).


### Removed

- **Node 18 support.** Node 18 reached End-of-Life in April 2025; the modern
test toolchain (vitest + rolldown) now imports `node:util.styleText`, which
only exists on Node 20.12+. The CI matrix was updated to Node 20/22/24 ×
Linux/macOS and `engines.node` was raised to `>=20.12.0`. The README's
install prerequisite changed from "Node.js ≥ 18" to "Node.js ≥ 20.12".

## [5.10.0] — 2026-05-23

Machine-portable project paths, plus repository/community-standards groundwork.
Expand Down Expand Up @@ -1127,24 +1249,17 @@ transitive, both functional, neither breaking. Tracked in road-006.

- **`gnosys dream run` — explicit manual trigger.** The bare `gnosys dream` already runs a cycle, but users naturally type `dream run` to match the `dream log` pattern. Added an alias subcommand. Both forms now check the central DB's `dream_machine_id` designation before running and refuse on non-designated machines unless `--force` is passed.


## [5.4.3] — 2026-05-02

### Fixed

- **Postinstall output now visible during `npm install -g`.** npm 7+ hides postinstall stdout for global installs but shows stderr — switched our messages to stderr so users actually see "Gnosys v5.4.3 installed / Run `gnosys upgrade`" after a global install.
- **Postinstall version read fixed.** Previously printed "Gnosys vunknown" because `require("fs")` doesn't work in ESM modules. Replaced with proper top-level `import { readFileSync }` and `import.meta.url`-based path resolution.
- **Postinstall output now visible during `npm install -g`.** npm 7+ hides postinstall stdout for global installs but shows stderr — switched messages to stderr so users see the installed version and upgrade hint after a global install.
- **Postinstall version read fixed.** Previously printed "Gnosys vunknown" because `require("fs")` doesn't work in ESM modules. Replaced with top-level `readFileSync` and `import.meta.url`-based path resolution.

### Added

- **Upgrade nudge on first CLI invocation.** Tracks `last_seen_version` in central DB meta. On every CLI command boot, if the installed version differs from what's stored, print a one-line stderr notice:
```
gnosys: upgraded to v5.4.3 (from v5.4.2). Run 'gnosys upgrade' to sync registered projects.
```
Fires once per upgrade, then updates the meta. Skipped when running `gnosys upgrade` itself, when `GNOSYS_SKIP_UPGRADE_NUDGE=1` is set, or when the central DB is unavailable. Belt-and-suspenders for cases where the postinstall hook silently fails (CI, Docker builds, `--ignore-scripts`).

### Known issue (deferred to v5.5.0)

- `npm install` still prints `npm warn deprecated prebuild-install@7.1.3: No longer maintained.` This is a transitive deprecation: `prebuild-install` is pulled in by `better-sqlite3` and (via `sharp`) by `@xenova/transformers`. The package still works correctly — the maintainer has just announced no future patches. Migrating `@xenova/transformers` (now a stale package) to `@huggingface/transformers@4.x` (the modern rebrand) is planned for v5.5.0 and will remove half of the dependency chain. The other half waits on `better-sqlite3` migrating to `node-gyp-build` upstream.
- **Upgrade nudge on first CLI invocation.** Tracks `last_seen_version` in central DB meta. When the installed version differs from what's stored, prints a one-line stderr notice, then updates meta. Skipped for `gnosys upgrade`, when `GNOSYS_SKIP_UPGRADE_NUDGE=1`, or when the central DB is unavailable.
- **`CODE_OF_CONDUCT.md`** at the repository root.

## [5.4.2] — 2026-05-01

Expand Down Expand Up @@ -1178,6 +1293,22 @@ The pattern is now consistent: `gnosys setup` runs the full wizard, and `gnosys
- gnosys-tests regression suite extended with `dream-log.test.ts`, `setup-dream.test.ts`, `removed-commands.test.ts`, plus DREAM HEALTH assertion in `dashboard.test.ts`.
- Manual smoke: dashboard surfaces DREAM HEALTH; designated machine probe runs at MCP boot; dream log filters work; removed commands return non-zero with "unknown command".

## [5.4.1] — 2026-05-01

### Added

- **Remote-first architecture.** Reads hit the remote NAS DB when reachable; local DB is an offline-only cache with a stderr fallback notice when remote is unreachable. `GnosysDB.openLocal()` for explicit local sync ops; `GNOSYS_LOCAL_ONLY=1` forces local-only mode.
- **ULID memory IDs** for new memories (`prefix-<ULID>`); existing prefix-N IDs unchanged.
- **Regression suite** extended for the v5.4.x architecture changes.

### Changed

- **Sync now includes the projects table** — `push()`, `pull()`, `sync()`, and `migrate()` sync project rows as well as memories. `SyncResult` gains `projectsPushed` / `projectsPulled` counters.

### Fixed

- Ten-bug sweep (B1–B10): central-DB routing for `gnosys graph` and dashboard project counts; removed stale dashboard labels; ESM-safe keychain lookup with Linux `secret-tool` support; dashboard border alignment; live ollama/lmstudio probes; deep-merge for `loadConfig`; SQLITE_CORRUPT recovery hints in MCP write errors; WAL autocheckpoint pragma; LLM error messages reference the configured provider's env var.

## [5.4.0] — 2026-04-30

### Added — three new IDE integrations
Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ src/
└── prompts/ # System prompts
```

## Documentation

For where each kind of doc belongs (user-facing site vs in-repo source of truth vs Gnosys memory), see [`docs/source-of-truth.md`](docs/source-of-truth.md).

## Testing

### Test Structure
Expand Down
24 changes: 18 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,31 @@ FROM node:20-alpine

WORKDIR /app

# Runtime needs git for history/rollback features
# Runtime needs git for history/rollback features (busybox provides wget for the healthcheck)
RUN apk add --no-cache git

# Copy built artifacts and production dependencies
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

# Create a default working directory for .gnosys vault
RUN mkdir -p /data
# v5.12: the brain lives on a host-local volume (/data). NEVER back this with an
# SMB/NFS share — network filesystems corrupt SQLite under gnosys's many small
# writes. GNOSYS_LOCAL_ONLY keeps this server authoritative (no remote hop).
ENV NODE_ENV=production \
GNOSYS_HOME=/data \
GNOSYS_LOCAL_ONLY=1

WORKDIR /data
RUN mkdir -p /data && chown -R node:node /data /app
USER node
VOLUME /data
EXPOSE 7777

# Default: start the MCP server (stdio mode)
# Set GNOSYS_SERVE_TOKEN at runtime to require `Authorization: Bearer <token>`.
HEALTHCHECK --interval=30s --timeout=5s --start-period=25s --retries=3 \
CMD wget -qO- http://127.0.0.1:7777/health || exit 1

# Network-hosted MCP. Binds 0.0.0.0 INSIDE the container (isolated); control
# external access with the host firewall / Tailscale + a bearer token.
ENTRYPOINT ["node", "/app/dist/cli.js"]
CMD ["serve"]
CMD ["serve", "--transport", "http", "--host", "0.0.0.0", "--port", "7777"]
Loading
Loading