Mirror of github.com/Memo-2023/mana-monorepo
Find a file
Till JS 6de01937cf feat(vault-client): phase 9 milestone 3 — recovery + zero-knowledge flows
Extends the browser-side vault client with five new methods that
mirror the server-side Phase 9 routes, plus a new
`awaiting-recovery-code` state that pauses the unlock mid-flow
when the server is in zero-knowledge mode.

VaultUnlockState gains a fourth variant
---------------------------------------
  | { status: 'awaiting-recovery-code' }

This is the state the client sits in between calling unlock()
(which received a recovery blob from GET /key) and the user typing
their recovery code into the UI. The settings page status badge
got updated to render this case as "🔑 Recovery-Code erforderlich".

New closure state inside createVaultClient
------------------------------------------
  - pendingRecoveryBlob: stash for the recovery wrap returned by
    GET /key in zero-knowledge mode. unlockWithRecoveryCode reads
    from here so the second round of input doesn't need a re-fetch.
  - cachedUnwrappedMkBytes: kept ONLY when the vault was unlocked
    via the recovery code path AND the user might want to disable
    zero-knowledge later (which needs to hand the MK back to the
    server for KEK re-wrapping). The standard unlock path leaves
    this null because the server already has the KEK wrap. Wiped
    on lock(), on disable success, and on any state transition
    that destroys the master key.

Modified existing methods
-------------------------
  - unlock(): branches on the response shape. If the server returns
    a recovery blob (zero-knowledge mode), stash it via
    awaitRecoveryCode() and return state='awaiting-recovery-code'.
    Otherwise unwrap as before. Same fork applies to the /init
    fallback path.
  - rotate(): if the server somehow returned a ZK shape (it should
    never — rotate is forbidden in ZK mode server-side), bail with
    a server error instead of silently misinterpreting bytes.
  - lock(): also clears pendingRecoveryBlob + wipes
    cachedUnwrappedMkBytes.

New methods (all wired into the returned VaultClient)
-----------------------------------------------------
  - setupRecoveryCode(): generates a fresh 32-byte recovery secret,
    derives the wrap key, re-fetches the active master key in
    extractable form, seals it, posts to /recovery-wrap, returns
    the formatted recovery code for the UI to display. Wipes both
    raw byte references after the seal. Caller is responsible for
    clearing the formatted string from memory once the user has
    confirmed they backed it up.

  - clearRecoveryCode(): DELETE /recovery-wrap. Server enforces the
    "not while ZK is active" rule.

  - enableZeroKnowledge(): POST /zero-knowledge { enable: true }.
    Maps RECOVERY_WRAP_MISSING server response to a clear "set up
    a recovery code first" client error.

  - disableZeroKnowledge(): POST /zero-knowledge { enable: false,
    masterKey: base64 }. Reads the cached MK bytes, base64-encodes,
    sends. Wipes the cache after success.

  - unlockWithRecoveryCode(code): completes the flow that started
    in unlock(). Parses the user-typed code (RecoveryCodeFormatError
    bubbles up if the shape is wrong), derives the wrap key, runs a
    single inline AES-GCM decrypt on the stashed blob (yields both
    the raw bytes for the cache AND a non-extractable runtime key
    for the provider), wipes raw bytes, transitions to 'unlocked'.

    Generic error message on failure ("wrong recovery code or
    corrupted vault") so an attacker can't distinguish wrong-code
    from tampered-blob. Stays in 'awaiting-recovery-code' on
    failure so the user can retry without a re-fetch.

Drive-by stale test fix
-----------------------
aes.test.ts had an assertion from Phase 1 that `tasks` and `events`
return null because they were on enabled:false. Phase 7.1 flipped
both tables on, so the assertion has been failing since that
commit. Replaced the test with a stable negative case
(non-existent table name) that doesn't shift with each rollout
phase.

Test results: 78/78 crypto tests pass after the fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 23:01:16 +02:00
.changeset feat(versioning): add semantic versioning and changesets to all apps 2026-03-19 16:20:18 +01:00
.claude feat(manacore/web): wire TagField, FavoriteButton, ColorPicker into module UIs 2026-04-02 17:20:46 +02:00
.github chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
.husky fix(devtools): fix pre-commit hook - add eslint-config dep, remove type-check 2026-03-17 13:08:51 +01:00
apps feat(vault-client): phase 9 milestone 3 — recovery + zero-knowledge flows 2026-04-07 23:01:16 +02:00
docker chore(macmini): infra cleanup — compose env, blackbox mem, prometheus gpu probes 2026-04-07 22:59:38 +02:00
docs docs: PRE_LAUNCH_CLEANUP.md — what we removed before launch and why 2026-04-07 22:32:14 +02:00
games chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
load-tests chore: rename mukke to music in infra, scripts, and CI/CD 2026-04-05 16:47:57 +02:00
NewAppIdeas/Roblox Reimagined chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
packages feat(cycles): add menstrual cycle tracking module 2026-04-07 14:35:33 +02:00
patches fix(traces): configure EAS Build for TestFlight and fix bot-services build 2026-03-17 13:16:38 +01:00
scripts chore(macmini/scripts): runbook hardening — status diff + ingress walk 2026-04-07 22:31:53 +02:00
services feat(mana-auth): phase 9 milestone 2 — vault recovery wrap + zero-knowledge 2026-04-07 22:05:49 +02:00
tests/e2e first implementation 2025-11-27 17:26:18 +01:00
.dockerignore make auth working 2025-11-26 01:31:12 +01:00
.editorconfig feat: add monorepo configuration and shared packages structure 2025-11-22 23:41:52 +01:00
.env.development feat(memoro): voice recording → mana-stt transcription pipeline 2026-04-07 18:48:41 +02:00
.env.macmini.example chore(macmini): pin COMPOSE_PROJECT_NAME=manacore-monorepo 2026-04-07 22:31:25 +02:00
.gitignore chore: misc fixes, new services, lockfile cleanup 2026-03-28 10:27:35 +01:00
.npmrc fix(monorepo): add .npmrc with node-linker=hoisted for EAS Build compatibility 2026-03-15 08:50:18 +01:00
.nvmrc feat: add monorepo configuration and shared packages structure 2025-11-22 23:41:52 +01:00
.prettierignore chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
.prettierrc.json fix(cicd): docker paths, formatting config, 2025-11-27 18:33:08 +01:00
CLAUDE.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
cloudflared-config.yml feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00
docker-compose.dev.yml feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00
docker-compose.macmini.yml chore(macmini): infra cleanup — compose env, blackbox mem, prometheus gpu probes 2026-04-07 22:59:38 +02:00
eslint.config.mjs chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
gift-codes-2026-02-14.txt feat(gifts): add gift code creation script and initial codes 2026-02-14 11:23:08 +01:00
lint-staged.config.js chore: archive 17 standalone app servers (replaced by unified API) 2026-04-02 21:37:45 +02:00
mac-mini-setup.sh feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00
package.json feat(events): add mana-events service + public RSVP flow (Phase 1b) 2026-04-07 14:27:48 +02:00
playwright.config.ts style: auto-format codebase with Prettier 2025-11-27 18:33:16 +01:00
pnpm-lock.yaml chore(workspace): unify vitest to ^4.1.2 across all packages 2026-04-07 13:58:29 +02:00
pnpm-workspace.yaml chore: delete 25 web-archived directories, remove stale stubs, clean workspace config 2026-04-03 13:03:49 +02:00
README.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
test-chat-auth.sh feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00
TROUBLESHOOTING.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
turbo.json feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00
vitest.config.ts feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00

Mana Monorepo

Monorepo containing all Mana projects — a self-hosted multi-app ecosystem with shared packages and unified tooling.

Projects

Project Description Apps
mana Multi-app ecosystem platform Expo mobile, SvelteKit web
chat AI chat application NestJS backend, Expo mobile, SvelteKit web, Astro landing
todo Task management NestJS backend, SvelteKit web, Astro landing
calendar Calendar & scheduling NestJS backend, SvelteKit web, Astro landing
clock Pomodoro & time tracking NestJS backend, SvelteKit web, Astro landing
contacts Contact management NestJS backend, SvelteKit web
picture AI image generation NestJS backend, Expo mobile, SvelteKit web, Astro landing
cards Card/deck management NestJS backend, Expo mobile, SvelteKit web
zitare Daily inspiration quotes NestJS backend, Expo mobile, SvelteKit web, Astro landing
mukke Music player NestJS backend, SvelteKit web
planta Plant care tracker NestJS backend, SvelteKit web
storage Cloud storage NestJS backend, SvelteKit web
questions Q&A with web search SvelteKit web
skilltree Skill tree visualization NestJS backend, SvelteKit web
nutriphi Nutrition tracking NestJS backend, SvelteKit web
citycorners City guide NestJS backend, SvelteKit web, Astro landing
presi Presentation tool NestJS backend, SvelteKit web
photos Photo management NestJS backend, SvelteKit web

Getting Started

Prerequisites

  • Node.js 20+
  • pnpm 9.15.0+
  • Docker (for PostgreSQL, Redis, MinIO)

Installation

pnpm install

Development

# Start infrastructure (PostgreSQL, Redis, MinIO)
pnpm docker:up

# Start any app with auto DB setup
pnpm dev:chat:full
pnpm dev:todo:full
pnpm dev:calendar:full
pnpm dev:contacts:full

# Build & quality
pnpm run build
pnpm run type-check
pnpm run format

See CLAUDE.md for comprehensive development documentation.

Architecture

mana-monorepo/
├── apps/                    # Product applications
├── services/                # Microservices (auth, search, LLM, bots)
├── packages/                # Shared packages
├── docker/                  # Docker configuration
└── scripts/                 # Development & deployment scripts

Tooling

  • Package Manager: pnpm 9.15.0
  • Build System: Turborepo
  • Formatting: Prettier (tabs, single quotes, 100 char width)
  • Hosting: Mac Mini (self-hosted) via Docker + Cloudflare Tunnel
  • Analytics: Umami (stats.mana.how)

License

Private - All rights reserved