Skip to content

chore(audit): security headers, smoke-on-tag CI, quickstart shape fix, doc refs#32

Merged
ppserapiao merged 1 commit into
mainfrom
chore/audit-fixes
May 22, 2026
Merged

chore(audit): security headers, smoke-on-tag CI, quickstart shape fix, doc refs#32
ppserapiao merged 1 commit into
mainfrom
chore/audit-fixes

Conversation

@ppserapiao
Copy link
Copy Markdown
Owner

Summary

Findings from a systematic launch-readiness audit (2026-05-22). The quickstart fix is the highest-impact item — every HN reader who copied the README literally would have hit matches[0].body === undefined before this.

  • README quickstart shape fixmneme.recall() returns { record, score }[], where record.body is itself { mode, data }. The previous quickstart wrote the call but showed nothing about how to read the result. Now the example iterates and prints record.body.data. Verified working against a fresh bun add @mnemehq/sdk @mnemehq/embedder-local in /tmp.
  • Security headers on landingapps/web/next.config.mjs now sets CSP (locked except for the unavoidable Next inline runtime/styles), X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and a Permissions-Policy disabling camera / microphone / geolocation / interest-cohort. HSTS was already set by Vercel — the rest were missing entirely. poweredByHeader: false stops leaking X-Powered-By: Next.js.
  • ARCHITECTURE.md broken refs — §6 "Published at mneme.dev/protocol" and §10 "Threat model published: mneme.dev/security/threat-model" both pointed at URLs we don't own. Now point at the in-repo docs/protocol/ draft and at ARCHITECTURE.md §5 + §11 / SECURITY.md respectively. Will move to canonical URLs when mneme.dev is provisioned.
  • Smoke in CI — new .github/workflows/smoke.yml runs bun run smoke (live-npm end-to-end) on a nightly cron, on every tag push, and on workflow_dispatch. Deliberately NOT on every PR — smoke pulls from live npm, so it's a release-gate signal, not a code-review signal. The nightly cron catches silent npm-registry / dependency drift between releases.

What this PR explicitly does NOT include (surfaced for Pedro's decision)

These came out of the audit but I held off rather than ship without your call:

  • WebSocket sync server rate limiting — currently has none. Acknowledged in code + README + ADR 0010 as "LAN-only, auth in v0.1.0 with Cloud." Adding a connection-cap defence-in-depth layer is ~20 lines. Ship now or defer to Cloud?
  • npm publish provenance (--provenance flag) — free, supply-chain attestation, no downsides. Worth enabling on the next publish.
  • Performance benchmark — CLAUDE.md non-negotiable claims sub-100ms P95. In this audit, in-memory recall after a fresh install measured ~6ms. We have anecdote, not measurement. A bun run bench script + tracked baseline closes this.
  • Self-hosted analytics on the landing — you asked about building ourselves; on-brand for "privacy is the product." ~1-day build, deferred to a follow-up PR.

Test plan

  • bun run build — green; security headers configured on all routes
  • bun run lint — 9 pre-existing warnings, none from this PR
  • bun run --filter '*' typecheck — green across all 9 packages
  • bun test — 185 pass / 2 skip / 0 fail
  • bun run smoke — 7/7 green on live npm (pre-branch verification on main)
  • README quickstart literal — verified end-to-end against a fresh bun add @mnemehq/sdk @mnemehq/embedder-local in /tmp: 0.35 preference — Prefers concise code review comments

Docs touched

  • README.md — quickstart shape fix + clearer Mneme.open() re-run comments
  • ARCHITECTURE.md — §6 and §10 broken references fixed
  • Memory: project_mneme_current_state.md ADR table extended 0011 → 0015 (was stale — ADRs 0012-0015 existed on disk but the table capped at 0011)

No protocol changes, no public API changes.

🤖 Generated with Claude Code

…, doc refs

Findings from a systematic launch-readiness audit (2026-05-22). The
quickstart fix is the highest-impact item — every HN reader who copies
the README would have hit `matches[0].body === undefined` before this.

Fixes:

1. apps/web/next.config.mjs — security headers on every route.
   CSP (locked except unavoidable Next inline runtime/styles),
   X-Frame-Options: DENY, X-Content-Type-Options: nosniff,
   Referrer-Policy: strict-origin-when-cross-origin, and a
   Permissions-Policy that disables camera / microphone / geolocation
   / interest-cohort. poweredByHeader off (small ergonomic cleanup;
   stops leaking "X-Powered-By: Next.js"). HSTS was already set by
   Vercel — the rest were missing entirely.

2. README.md quickstart — `mneme.recall()` returns
   `{ record, score }[]`, where `record.body` is itself
   `{ mode, data }`. The previous quickstart wrote the call but
   showed nothing about how to read the result, so a literal
   copy-paste left the reader with `matches[0].body === undefined`.
   Now the example iterates `{ record, score }` and prints
   `record.body.data` — verified working against a fresh
   `bun add @mnemehq/sdk` in /tmp. Also added explicit `path:` to
   the `Mneme.open()` comments so re-runs don't trip the
   "keyring already exists" conflict.

3. ARCHITECTURE.md — two broken references to `mneme.dev` paths
   we don't own:
     §6: "Published at `mneme.dev/protocol`" → points at the in-repo
         `docs/protocol/` draft, will move when domain is provisioned.
     §10: "Threat model published: `mneme.dev/security/threat-model`"
         → points at ARCHITECTURE.md §5 + §11 (the actual threat
         model) and at SECURITY.md (the live disclosure path).
   A DD reviewer would otherwise see "we say X is published at Y"
   and find Y 404-ing.

4. .github/workflows/smoke.yml — runs `bun run smoke` (the live-npm
   end-to-end verification) on a nightly cron, on every tag push, and
   on workflow_dispatch. Deliberately NOT on every PR — smoke pulls
   from live npm, so it's a release-gate signal, not a code-review
   signal. The nightly cron catches silent npm-registry or
   dependency drift between releases.

Memory updates (in lockstep):

- `project_mneme_current_state.md` ADR table extended 0011 → 0015
  (was stale — ADRs 0012-0015 existed on disk but the table
  capped at 0011).

What this PR explicitly does NOT include (surfaced for Pedro):

- Rate limiting on the WebSocket sync server. Currently has none.
  Acknowledged in code + README + ADR 0010 as "LAN-only, auth in
  v0.1.0 with Cloud." Adding a connection-cap defence-in-depth
  layer is ~20 lines; ship or defer to Cloud?
- npm publish provenance (`--provenance` flag). Free, supply-chain
  attestation, no downsides. Worth enabling on the next publish.
- Performance benchmark. CLAUDE.md non-negotiable claims sub-100ms
  P95; in this audit, in-memory recall after a fresh install
  measured ~6ms. We have anecdote, not measurement. A
  `bun run bench` script + a tracked baseline closes this.
- Self-hosted analytics on the landing. Pedro asked about building
  ourselves; on-brand for "privacy is the product." ~1-day build.

Test plan:
- bun run build — green; security headers configured on all routes
- bun run lint — 9 pre-existing warnings, none new
- bun run --filter '*' typecheck — green across 9 packages
- bun test — 185 pass / 2 skip / 0 fail
- bun run smoke — 7/7 green on live npm (run pre-branch on main)
- README quickstart literal — verified end-to-end against a fresh
  `bun add @mnemehq/sdk @mnemehq/embedder-local` in /tmp:
  `0.35 preference — Prefers concise code review comments`

Docs touched: README.md, ARCHITECTURE.md.
No protocol changes, no public API changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mneme-web Ready Ready Preview, Comment May 22, 2026 6:14pm

@ppserapiao ppserapiao merged commit caef9bc into main May 22, 2026
4 checks passed
@ppserapiao ppserapiao deleted the chore/audit-fixes branch May 22, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant