brain backup 2026-09-14

This commit is contained in:
Adolfo Reyna
2026-09-14 22:38:47 -04:00
parent ca346cc6e7
commit f0ead4f6fa
147 changed files with 73451 additions and 8 deletions
+19
View File
@@ -0,0 +1,19 @@
# Factory Project Definitions
This directory holds one concise definition for each **our project** managed through the Paseo software-factory model.
| Key | Definition | Current focus |
|---|---|---|
| `emi` | [EMI](emi.md) | Multi-repository ministry application and production backend mapping |
| `reyna-cli` | [Reyna CLI](reyna-cli.md) | Privacy-sensitive macOS operations platform |
| `tactility` | [Tactility](tactility.md) | ESP32 platform, runtime apps, and approved device delivery |
| `family-voice` | [Family Voice](family-voice.md) | Privacy-first voice context and speaker-ID prototype |
| `kids-hermes-voice` | [Kids Hermes Voice](kids-hermes-voice.md) | Child-safe Tactility client, voice gateway, and Hermes runtime integration |
| `remarkable-hermes` | [reMarkable Hermes](remarkable-hermes.md) | Paper Pro communication app and watcher recovery |
## Rules
- A project definition is our cross-server management record.
- The project definition points to every relevant server-local Paseo project; it does not replace them.
- Repository-local `AGENTS.md` governs code work; `../AGENTS.md` governs project-management work.
- Add a new definition before creating factory agents/schedules for a new project.
@@ -0,0 +1,29 @@
# EMI Expo prayer localization commit — 2026-08-18
Repository: `/Users/adolforeyna/Projects/EMI/expoApp` (branch `master`)
## Approved cleanup and commit
- Removed the untracked generated `ios/` directory.
- Restored `package.json` to `HEAD`; it was not staged or committed.
- Commit: `2a09d56a9b5de24c1193a74eef807977a50fdacd`
- Message: `feat(prayer): localize the 15-minute prayer experience`
## Staged and committed files
1. `Views/PrayerTimer.js`
2. `components/PrayerTracker.js`
3. `i18nMessages.js`
## Verification
- Staged-file allowlist check passed before commit; the staged set exactly matched the three files above.
- `git diff --cached --check` passed.
- `node --check Views/PrayerTimer.js` passed.
- `node --check components/PrayerTracker.js` passed.
- `node --check i18nMessages.js` passed.
- Post-commit verification confirmed the commit contains exactly the three approved files, `ios/` is absent, and the staging area is empty.
## Remaining worktree state
Clean: `git status --short` produced no output. No push, branch change, package installation, native build, or service action was performed.
@@ -0,0 +1,64 @@
# EMI local translation production readiness — 2026-08-18
## Goal
Read-only production-readiness discovery for EMI’s local MarianMT translation service and deployed backend integration.
## Scope and boundaries
- **Project / hosts:** EMI; Mac mini `.102` as Factory/Paseo control host and EMI production server `.119` as the intended runtime host.
- **Repository / runtime:** Mac-mini backend workspace `/Users/adolforeyna/Projects/EMI/EMI-Backend`; intended production checkout `/home/aeroreyna/EMI-Backend` and its Docker Compose backend/translation containers.
- **Allowed:** explicit `auto-review` Paseo verifier; non-mutating source/runtime inspection and bounded non-persistent HTTP only where runtime access is available.
- **Forbidden:** edits, commits, pushes, pulls, stashes/resets/cleans, image build/pull/rebuild, service/container restart/recreate/deploy, migrations, credential or configuration changes, and proxy/firewall changes.
- **Approval gate:** human approval before any isolated worktree, source/configuration change, merge, deployment, restart, or container lifecycle action.
## Coordinator continuity
- Feature session: `emi: local-translation-production-readiness` (Factory profile).
- Existing production Paseo workspace recorded by project definition: `wks_fc39b6c9d2ebc9e0` on `.119`; it was not reachable from this Factory control session because the production daemon is loopback-only and direct SSH as `aeroreyna@emi-server` was denied.
## Paseo evidence
| Role | Agent ID | Workspace ID | Provider / mode | Terminal state |
|---|---|---|---|---|
| Read-only runtime verifier | `9b8ca9a7-193f-4162-bd3d-d9f861a518d9` | `wks_740a1fe0494b5cc9` (`EMI · Backend — Mac mini Checkout`) | `codex/gpt-5.6-terra`, explicitly `auto-review` | `idle` / completed |
The agent located/read the applicable parent workspace guidance before source inspection. Paseo inspection confirmed its available mode included `auto-review`, no pending permissions, and no worktree was created. No source or runtime mutation was requested or reported.
## Observed contract (static only — not production runtime verification)
The verifier’s read-only source inspection found:
- Compose intends an internal `app` ↔ `translation` connection on `emi-network`; app upstream is `http://translation:8000`. Translation has no published host port.
- The app defaults to `TRANSLATION_PROVIDER=openai`; local MarianMT is used only when the runtime provider is explicitly `marian`.
- `GET /health` is implemented as `200 application/json` with `{"status":"ok","provider":"marianmt","loadedModels":[...]}`. This is a liveness/in-memory model-name signal only; it does not prove required-model cache availability, successful inference, or readiness.
- `POST /translate` accepts `text`, `sourceLang`, and `targetLang`. Missing/invalid text or target and unsupported languages are intended to return `400`; unhandled translation failures are intended to return `502 {"status":"Translation failed"}`.
- Models load lazily on first translation into `/models`; the app’s upstream timeout is 30 seconds.
- Compose declares neither a container healthcheck nor CPU/memory limits.
## Runtime-verification result and blocker
The verifier attempted only read-only runtime-discovery commands (`docker compose ps --all`, filtered `docker ps`, and filtered `docker volume ls`) and found `docker: command not found`; `docker-compose`, `podman`, and `nerdctl` were also unavailable. Process inspection was restricted (`ps: operation not permitted`), and no listener on local ports 8000 or 3001 was observable.
Accordingly, it did **not** install tools, alter permissions, authenticate, enter containers, inspect caches, invoke a translation request, or induce a model download. The only completed evidence is the static contract above. The following production facts remain unverified: running container identity/network/upstream; actual provider value; app-to-translation DNS/TCP/HTTP; `/health` response from the deployed service; functional translation; first-download/cache behavior; live invalid/upstream-timeout behavior; current resource use; and deployed resource limits.
## Exact production-readiness acceptance criteria
Production readiness is not met until a read-only verifier with access to the actual `.119` Compose runtime records all of the following:
1. **Runtime identity and isolation:** exact app and translation container IDs/images, Compose project, Docker network membership, and non-secret app upstream mapping; translation is reachable only through the intended internal path unless explicitly approved otherwise.
2. **Provider correctness:** runtime evidence that the app is configured to use `marian`, not the static default `openai`, and that its upstream resolves to the intended translation service.
3. **Connectivity:** a non-mutating request from the running app container resolves `translation`, completes TCP/HTTP to port 8000, and receives the expected response within the configured bound.
4. **Health/readiness semantics:** exact deployed `/health` status, headers, and body are captured; a readiness criterion explicitly proves every required model is locally available for inference without triggering a download. A liveness-only `200` is insufficient.
5. **Functional translation:** one bounded, innocuous translation for each approved language direction succeeds through the app’s real translation path; response schema/text and elapsed time are recorded, with no user data persisted.
6. **First-model/cache behavior:** cache volume/path, ownership, persistence across planned container recreation, and required model artifacts are evidenced. First-download latency, network dependency, disk impact, and failure behavior are measured in a controlled approved environment—not by deleting a production cache.
7. **Errors and timeouts:** invalid request returns a documented non-5xx client error; upstream unavailable/timeout behavior is tested without stopping production (or in an approved equivalent environment) and returns the documented bounded error without crashing/retrying indefinitely; the app’s 30-second upstream bound is verified.
8. **Resources:** deployed CPU/memory reservation/limit and current idle/translation peak CPU, RSS, disk/cache consumption are recorded; observed peaks stay below an owner-approved host budget with headroom. No configured resource limits is a blocker.
9. **Operational controls:** Compose/service healthchecks, logs/metrics sufficient to distinguish model download, model load, inference failure, timeout, and resource exhaustion, plus an approved rollback procedure, are documented and independently checked.
10. **Release integrity:** all implementation changes exist in one isolated worktree, pass declared checks, receive independent review, and obtain explicit human approval before merge/build/recreate/deploy.
## Proposed isolated-worktree implementation plan (not authorized or started)
1. Obtain a read-only production-runtime observability path (Paseo agent on `.119` or authorized Docker metadata/log/exec access) and complete acceptance items 1–8 without lifecycle changes.
2. After human approval and protection/review of the dirty production Compose state, create one isolated backend worktree from the approved committed base, e.g. branch `factory/emi-local-translation-readiness`; do not use either dirty main checkout.
3. Implement a non-downloading readiness endpoint/check that verifies configured required models are present and loadable; keep existing liveness semantics separate and document status/error contracts.
4. Add Compose healthchecks and explicit, owner-approved CPU/memory constraints; make model-cache volume persistence, permissions, and prewarming strategy explicit.
5. Add deterministic tests for provider selection, health/readiness distinction, validation errors, upstream timeout/error mapping, and cache-present/cache-absent behavior without external model downloads in ordinary CI.
6. In an approved non-production environment, measure cold first-download, warm-cache translation, resource peaks, timeout behavior, and recovery; document production rollout and rollback steps.
7. Dispatch an independent reviewer and verifier against that isolated worktree. Present exact diff, checks, measured evidence, deployment/recreate impact, and rollback plan for explicit human approval; only then may a named deployment executor act.
@@ -0,0 +1,173 @@
# EMI pre-commit decision review — 2026-08-18
Scope: read-only review of candidate changes in the two Mac mini (`.102`) repositories only. No commit, staging, pull, rebase, push, install, service action, or source edit was performed. Diff content was reviewed as data; this report intentionally contains no secret values.
## Task record
- Project: EMI.
- Repositories reviewed: `~/Projects/EMI/expoApp` (branch `master`; remotes `gitea` and `origin`) and `~/Projects/EMI/EMI-Backend` (branch `codex/bible-verse-notes`; remote `gitea` only).
- Acceptance criteria: identify commit-ready candidate sets, generated-file disposition, validation evidence, blockers, and the later server approval boundary.
- Forbidden effects observed: none; all inspection commands were read-only.
- Repository instructions: parent `~/Projects/EMI/AGENTS.md` and each repository's `Agent.md` were read. App instructions require explicit approval before a change requiring a new App Store build; backend instructions prefer Node 20 LTS and describe `npm test` as the only test command.
## expoApp
### Candidate scope
Tracked modifications:
- `Views/PrayerTimer.js`
- `components/PrayerTracker.js`
- `i18nMessages.js`
- `package.json`
Untracked native output is limited by `git status` to 25 explicitly listed `ios/` files (Xcode project/workspace, application files, asset catalogs, Podfile/lockfile, and generated Expo settings). The ignored `ios/` tree also contains dependency output and five `.DS_Store` files.
The application change makes the prayer duration 15 minutes, localizes prayer-tracker/timer strings in all existing language blocks, localizes weekday rendering, and changes the native run scripts from Expo start targets to `expo run:android` and `expo run:ios`.
### Generated `ios/` decision
Include the 25 status-listed `ios/` source/configuration files only if the intent is to adopt and maintain the generated native iOS project alongside the new `expo run:ios` script. They are a coherent companion to that script change: omitting them leaves the new native-run workflow without its required project files.
Do not stage `ios/` recursively. Do not stage `ios/Pods/`, any ignored native dependency/build output, or any `.DS_Store` file. The status-listed project files should be staged explicitly, not by a broad directory add. The native project has not been built or opened during this read-only review, and the repository instruction requires explicit approval before a change that requires a new App Store build. Committing project sources alone is not an App Store build, but their intended native-build effect needs owner confirmation and native validation before this set is accepted as-is.
### Blocking findings
1. Native iOS project adoption is unconfirmed and unvalidated. The new `npm run ios` invokes `expo run:ios`, while its generated project and lockfile are untracked. Commit intent, an approved native-build validation scope, and successful native validation are missing.
2. The only safe complete native staging set must be explicit; a recursive `ios/` add risks picking up later generated or ignored local material. `.DS_Store` is categorically excluded.
### Non-blocking findings
- The prayer/localization diff is internally scoped and all newly referenced translation keys exist in each existing language block.
- `PrayerTracker` now passes the active `i18n.locale` to weekday formatting; supported locale values are normalized language codes.
- `git diff --check` returned clean; `node --check` passed for all three modified JavaScript files; `package.json` parsed as valid JSON.
- No app test, lint, typecheck, or build script exists in `package.json`; no local validation/report/log artifact was found.
- A changed-diff credential-pattern scan found no private-key block or common credential assignment/token pattern. This is heuristic evidence only, not a secrets guarantee.
### Safe staging lists and commit split
Commit 1 — prayer experience and localization:
```text
Views/PrayerTimer.js
components/PrayerTracker.js
i18nMessages.js
```
Recommended message:
```text
feat(prayer): localize the 15-minute prayer experience
```
Commit 2 — only after confirmation that native iOS sources are intended and native validation is approved/passes:
```text
package.json
ios/.gitignore
ios/.xcode.env
ios/EMISocial.xcodeproj/project.pbxproj
ios/EMISocial.xcodeproj/xcshareddata/xcschemes/EMISocial.xcscheme
ios/EMISocial.xcworkspace/contents.xcworkspacedata
ios/EMISocial/AppDelegate.h
ios/EMISocial/AppDelegate.mm
ios/EMISocial/EMISocial-Bridging-Header.h
ios/EMISocial/EMISocial.entitlements
ios/EMISocial/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png
ios/EMISocial/Images.xcassets/AppIcon.appiconset/Contents.json
ios/EMISocial/Images.xcassets/Contents.json
ios/EMISocial/Images.xcassets/SplashScreen.imageset/Contents.json
ios/EMISocial/Images.xcassets/SplashScreen.imageset/image.png
ios/EMISocial/Images.xcassets/SplashScreenBackground.imageset/Contents.json
ios/EMISocial/Images.xcassets/SplashScreenBackground.imageset/image.png
ios/EMISocial/Info.plist
ios/EMISocial/PrivacyInfo.xcprivacy
ios/EMISocial/SplashScreen.storyboard
ios/EMISocial/Supporting/Expo.plist
ios/EMISocial/main.m
ios/EMISocial/noop-file.swift
ios/Podfile
ios/Podfile.lock
ios/Podfile.properties.json
```
Recommended message:
```text
chore(ios): add Expo native project for local iOS runs
```
Explicit exclusions:
```text
.DS_Store
**/.DS_Store
ios/Pods/
ignored generated native dependency/build output
```
### Commit-as-is recommendation
No. The prayer/localization subset is structurally suitable for its own commit, but the repository as currently combined includes unconfirmed, unvalidated generated native iOS output and a native-run workflow change.
## EMI-Backend
### Candidate scope
Tracked modifications:
- `config/cookiesOptions.js`
- `config/corsOptions.js`
- `index.js`
Untracked file:
- `.DS_Store` — exclude; do not stage or commit.
The candidate broadens local-cookie detection to every IPv4 address in the private `192.168.*.*` range, changes CORS from an array to a callback that admits any HTTP origin in that same range (and any localhost loopback port), adds selected local Expo development origins, and binds the server to `HOST` or all interfaces by default.
### Blocking finding
1. Do not commit this backend set as-is. Credentials-enabled CORS is enabled for any HTTP origin on the entire `192.168.*.*` private range regardless of environment, and cookie handling treats a matching request Origin or Host as local and therefore permits non-secure, `SameSite=Lax` cookies. These are production-relevant security-policy changes, not a bounded local-development setting. The code does not gate the broad LAN rules to a non-production environment, restrict them to approved development origins, or establish trusted-proxy/host-header handling. Security review and an explicitly approved environment-specific policy are required before staging these three files.
The default all-interface bind heightens the need for that review: whether it is necessary, and its firewall/proxy/deployment implications, have not been validated in this task.
### Non-blocking findings
- `git diff --check` returned clean; `node --check` passed for all three modified JavaScript files; `package.json` parsed as valid JSON.
- `package.json` declares `npm test` as `npx mocha test/auth.test.js`; it has no lint, typecheck, or build script. No local validation/report/log artifact was found.
- Existing validation evidence supplied for this review: under Node 22, `npm test` failed because of legacy dependency incompatibility. Under Node 20, the two auth tests passed but the process did not exit because it retained a listener. Source inspection confirms the test starts a listener and closes that listener in its `after` hook; importing the application can still retain other handles. This test is integration/data dependent and is not clean CI evidence until it exits deterministically.
- A changed-diff credential-pattern scan found no private-key block or common credential assignment/token pattern. This is heuristic evidence only, not a secrets guarantee.
### Safe staging list and commit split
There is no safe staging list for the current backend candidate until the blocking security-policy decision is resolved. Keep all three modified files unstaged and exclude `.DS_Store`.
After a reviewed implementation supplies a production-safe, environment-gated policy and it is validated in an isolated worktree, separate commits should be:
```text
fix(dev): scope LAN cookie and CORS support to approved development origins
```
for the cookie/CORS policy files, and:
```text
fix(server): make backend bind host configurable
```
for `index.js`, only if the deployment/network review confirms that bind behavior is required.
### Commit-as-is recommendation
No.
## Later EMI-server checkout update/rebase/push — exact human approval boundary
The requested Mac mini commits do not authorize any action on the EMI server checkout. A separate, explicit human approval is required after the Mac mini commits are reviewed and identified by their exact commit IDs, and before any server-side update, fetch, pull, rebase, conflict resolution, push, service action, image build, container recreation, restart, or deployment.
That approval must name all of the following: the server checkout and target branch; the approved remote and exact Mac mini commit IDs; whether a rebase is authorized; the allowed update/push commands; the named executor; conflict policy (stop and report, no automatic resolution); required pre/post checks; and the rollback owner/procedure. It must also follow a current read-only server audit confirming the checkout-to-running-container relationship, service/deployment procedure, health endpoint, rollback path, and disposition of the server's existing local modifications and untracked update script. The known server checkout is dirty, so no rebase/push action may be inferred from a Mac mini commit.
## Overall decision
- `expoApp`: NO — do not commit the combined repository state as-is; the prayer/localization subset may proceed only as its separate commit, while the native iOS set awaits explicit intent/validation.
- `EMI-Backend`: NO — do not commit as-is; security-policy blockers require review and correction before staging.
@@ -0,0 +1,46 @@
# EMI production perimeter audit — 2026-08-18
## Scope and verdict
Read-only perimeter follow-up on `aeroreyna@192.168.68.119` (`emiserver`). Inspected only non-secret listener/firewall service facts, Docker published-port/network/container metadata, detected proxy metadata, DNS, and unauthenticated HTTP `GET`, `HEAD`, and `OPTIONS` behavior. No authentication, form submission, secret/environment/configuration reading, dirty Compose diff inspection, source modification, service/container/proxy/firewall change, or Mac-mini backend WIP interaction occurred.
**Verdict: perimeter is not production-clean.** Authentication controls prevent unauthenticated root access to the backend, and the tested origins were not granted browser CORS read access. However, the EMI backend remains directly published on every IPv4 and IPv6 interface at TCP 3001; the effective UFW rule policy could not be read without elevation; and the intended public frontend/API origin and proxy path remain unproven. Do not infer a proxy-only or firewall-restricted production posture.
## Verified exposure controls
- `ufw.service` is enabled and active (exited). This verifies that UFW is installed/enabled, not which allow/deny rules are effective; unprivileged `ufw status`, `iptables`, and `nft` rule reads were denied and no elevation was attempted.
- The backend container is `emi-backend-app-1` (Compose project `emi-backend`, service `app`) with restart policy `always`.
- Direct, unauthenticated backend root requests at `http://127.0.0.1:3001/` returned `401 Unauthorized` for both `GET` and `HEAD`; neither response carried a redirect location. The `HEAD` probe's status/header result is valid, although curl reported a transfer-length warning after the server advertised a body.
- The same direct backend preflight (`OPTIONS`, `Origin: https://emmint.com`, `Access-Control-Request-Method: GET`) returned `204 No Content`, `Vary: Origin, Access-Control-Request-Headers`, `Access-Control-Allow-Credentials: true`, and `Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE`.
- Direct preflights for `https://emmint.com`, `https://www.emmint.com`, `https://florida.emmint.com`, `https://api.emmint.com`, and `https://invalid.example` returned no `Access-Control-Allow-Origin`. Thus none of those tested browser origins was granted cross-origin read access by the direct backend response.
- `api.emmint.com` resolved to `76.108.184.110`. Its unauthenticated HTTPS root behavior was `302 Found` with `Location: /login` for both `GET` and `HEAD`; its preflight was `204 No Content`. The public responses identify an upstream Caddy (`Via: 1.1 Caddy`) and Express application; no `Access-Control-Allow-Origin` was observed on the tested public preflight.
## Listener, container, network, and proxy facts
- `emi-backend-app-1` publishes `3001/tcp` as `0.0.0.0:3001` and `[::]:3001`, confirmed both by Docker and the host listener table. It is not loopback-only.
- The backend is attached to Docker bridge `emi-backend_default`, whose metadata is `internal=false`, `attachable=false`, and IPv6 disabled. The container has a read-write bind mount from `/home/aeroreyna/EMI-Backend` to `/app`, a read-write node-modules volume, and `ReadonlyRootfs=false`.
- Other all-interface TCP listeners observed on `.119` were 22, 222, 2283, 3000, 8085, 9000, 9001, 9443, and 18789–18790. Docker metadata attributes these to Immich, Gitea, Nextcloud, Authentik, Portainer Agent, and OpenClaw as applicable. This audit makes no claim that each is reachable outside the host/LAN because effective firewall and upstream NAT policy were not readable.
- The Paseo daemon listens only on `127.0.0.1:6767`; an OpenCode process listens only on `127.0.0.1:45243`.
- No Caddy, Nginx, Traefik, HAProxy, or Apache systemd unit was found. Apache processes were present, but no port 80/443 listener was present in the host listener table. No Docker reverse-proxy container was present. The Caddy observed at public `api.emmint.com` is therefore not verified as a local `.119` service/container; its upstream placement and forwarding policy remain unresolved.
- Documented frontend hostnames resolve away from the `.119` LAN address: `emmint.com` and `www.emmint.com` to `198.175.150.40`, and `florida.emmint.com` to `35.164.64.246`. Their unauthenticated HTTPS root behavior was consistent with external WordPress/LiteSpeed (`emmint.com`: `GET`/`HEAD` 301 to `www`; `OPTIONS` 200), `www.emmint.com` (`GET`/`HEAD`/`OPTIONS` 200), and an external Caddy-backed site for `florida.emmint.com` (`GET`/`HEAD`/`OPTIONS` 200). They are not verified `.119` reverse-proxy frontends.
## Unresolved exposure and CORS findings
1. **Direct API exposure remains the primary perimeter finding.** TCP 3001 is published to all host interfaces and the Docker network is non-internal. UFW's active rule set and the router/NAT policy were intentionally not elevated/read, so this audit cannot establish whether LAN or Internet clients can reach the direct port.
2. **Public API proxy topology is unresolved.** `api.emmint.com` presents Caddy/Express behavior and redirects unauthenticated `GET`/`HEAD` to `/login`, but its public address does not identify the local `.119` LAN endpoint and no local Caddy listener/container was found. It is not proven whether the proxy protects all API paths, which upstream it uses, or whether direct 3001 bypasses it.
3. **CORS is deny-by-observation, not intent-verified.** Every tested direct preflight, including `https://emmint.com`, lacked `Access-Control-Allow-Origin`; the tested public API preflight also lacked it. This blocks browser cross-origin reads for those requests, but it does not establish the intended credentialed frontend origin or prove that a production frontend can call the API successfully. `Access-Control-Allow-Credentials: true` is present without a tested allowed origin.
4. **Published public websites are not evidence of an API frontend.** The documented `emmint.com`, `www.emmint.com`, and `florida.emmint.com` hostnames resolve to third-party/external web endpoints rather than verified `.119` proxy listeners. No documented production frontend hostname was shown to be an allowed CORS origin for this API.
## Context received after audit
**Authoritative infrastructure context:** `api.emmint.com` is served by Caddy on FamReynaServer `.110`, which routes to the EMI backend on `.119`. That shared Caddy/Authentik/DNS/firewall layer is outside the EMI project's ownership. This report's observation that the proxy placement was unresolved is therefore superseded as a project-boundary question: the route may be documented and health-verified by EMI work, but must not be modified by an EMI task. Any proxy remediation needs a separately scoped shared-infrastructure task and explicit approval.
## Minimal remediation options — require explicit human approval
Choose only after confirming the intended API hostname, frontend origin(s), required credential mode, and LAN/Internet exposure policy:
1. **Proxy-only API:** bind Docker `3001` to loopback only (or remove the host publication), then explicitly proxy the required HTTPS API hostname through the approved reverse proxy. Review the dirty Compose change in an isolated worktree before any lifecycle action.
2. **Firewall-restricted direct API:** retain the published port only if necessary, and approve explicit UFW/router rules limiting 3001 to the named trusted proxy/LAN sources. Verify from an authorized external and LAN vantage point after the approved change.
3. **Explicit CORS allowlist:** configure only the confirmed HTTPS frontend origin(s), preserve `Vary: Origin`, and test allowed and denied preflights plus an unauthenticated request through the real proxy. Do not use a wildcard origin with credentialed requests.
Any option requires separate approval for configuration review/change, rebuild/recreate/restart, deployment, or firewall/proxy modification. The Mac-mini backend CORS WIP remains untouched and uncommitted.
@@ -0,0 +1,54 @@
# EMI production security audit — 2026-08-18
## Scope, safety boundary, and verdict
Read-only audit of `aeroreyna@192.168.68.119`, `~/EMI-Backend`, and the running `emi-backend-app-1` container. No services, containers, checkout files, Git state, firewall/proxy configuration, credentials, environment values, compose diff content, or Mac-mini WIP were changed. No secret values were read or recorded.
**Verdict: conditionally acceptable to remain running, but not production-security clean.** The live application source files that control the observed server behavior match the `.119` checkout's `HEAD` commit `92320c9c8993308172282d6ac4437e19c752650a` (`Add monthly MongoDB backup script`, 2026-05-29). The server should not be recreated or redeployed without human review because its local compose file is modified relative to that commit.
The main `.119` server may remain on its current deployed commit while the separate Mac-mini backend WIP remains uncommitted. This audit made no change to that WIP. The conclusion is limited to keeping the existing `.119` container running; it is not approval to rebuild, recreate, deploy, merge, or commit anything.
## Evidence and runtime identity
- Checkout `HEAD`: `92320c9c8993308172282d6ac4437e19c752650a`.
- Checkout status: one tracked modified file and one untracked file. The tracked `docker-compose.yml` differs from `HEAD`; its diff content was neither read nor displayed.
- Running container: `emi-backend-app-1`; image `emi-backend-app`; image ID `sha256:0f245f652484e3704723cb93717b9ca867c38e74d8eb05eab7b123fa638eef44`.
- Image/container creation: 2026-05-29; current container start: 2026-08-17. Restart policy: `always`.
- The container bind-mounts `/home/aeroreyna/EMI-Backend` read-write at `/app`. It therefore executes checkout-mounted application files rather than an isolated immutable copy of those files.
- SHA-256 comparisons (without exposing file content) show the running `/app/index.js`, `/app/package.json`, `/app/config/corsOptions.js`, and `/app/config/cookiesOptions.js` each match the corresponding `HEAD` file. The checkout versions of those same files and `Dockerfile` also match `HEAD`.
## Verified-good controls
- The root request on `127.0.0.1:3001` returned `401 Unauthorized`, rather than an unauthenticated success response. No `Location` redirect header was observed.
- Preflight requests returned `204 No Content`, with `Vary: Origin, Access-Control-Request-Headers`; ordinary requests returned `Vary: Origin`. This prevents a shared cache from treating all origin variants as identical.
- Both tested origins (`https://emmint.com` and an intentionally invalid external origin) received no `Access-Control-Allow-Origin` header. In a browser, neither tested origin is granted cross-origin read access by that response.
- The server returned `Access-Control-Allow-Credentials: true`, so the observed CORS behavior is configured for credentialed requests only when an origin is explicitly permitted.
- The committed cookie-options source contains an `HttpOnly` control marker and that file is byte-identical in the running container. This establishes that the committed runtime file includes that control, not that every authentication flow actually emits a correctly flagged cookie.
## Risks and findings
1. **Public API port exposure — high-priority review.** Docker publishes `3001/tcp` on `0.0.0.0:3001` and `[::]:3001`, not loopback only. The container is on a non-internal Docker bridge (`emi-backend_default`, `internal=false`). Network/firewall enforcement outside Docker was not changed or assumed. If the intended posture is proxy-only API access, this is broader exposure than intended.
2. **Mutable production code path — high-priority operational risk.** The production container bind-mounts the checkout read-write at `/app`, and the container root filesystem is not read-only. A checkout edit can affect the running process or subsequent restarts outside an immutable-image release boundary.
3. **Dirty compose checkout — release-integrity blocker.** The only tracked modification is represented by the dirty `docker-compose.yml` check; its contents were deliberately not inspected. Current process-critical application files match `HEAD`, but a future recreate/restart through Compose may use uncommitted configuration. Do not treat a recreate as reproducing committed production source until reviewed in an isolated worktree.
4. **CORS intent is not fully proven.** Both tested origins lacked `Access-Control-Allow-Origin`, including `https://emmint.com`. This is safe against those specific browser origins, but it may also mean the intended production frontend origin was not tested, is unavailable under that exact hostname, or is misconfigured. The audit cannot claim that the intended frontend works, nor that every unwanted origin is rejected.
5. **Cookie flags are not runtime-verified.** No non-mutating endpoint in this audit emitted a `Set-Cookie` header, so `Secure`, `SameSite`, domain/path scope, and actual issuance behavior remain unverified. No authentication request was made.
## Unknowns
- Which exact public frontend origins are intended and whether each should be allowed with credentials.
- The effective firewall, upstream reverse-proxy, TLS termination, and Internet/LAN reachability policy for published port 3001.
- Whether the untracked file or modified compose file affects a future Compose lifecycle action; neither content was read.
- The running Node process's precise listener address inside the container, health endpoint, authentication-cookie issuance path, and behavior through the public proxy/TLS route.
- Whether image dependencies in `/app/node_modules` correspond to the committed lockfile; the named volume was not inspected.
## Required human approval before remediation
Any remediation requires explicit owner approval before: reviewing the dirty compose diff; creating an isolated worktree; modifying Docker/Compose, CORS, cookies, listener binding, reverse proxy, firewall, or image build; rebuilding/recreating/restarting the container; committing/merging; or deploying. The Mac-mini backend WIP must remain uncommitted and untouched unless separately approved.
## Next recommended task
Approved read-only follow-up: identify the intended EMI public frontend origin(s) and probe only their localhost-proxied, non-authenticated `GET`/`OPTIONS` responses for CORS headers; then separately inventory the reverse-proxy and firewall exposure without changing either.
@@ -0,0 +1,29 @@
# EMI production vs latest code — 2026-08-18
Read-only comparison. No fetch/pull, checkout, container/service change, or dirty-diff content inspection was performed.
## Committed-code relationship
- Mac mini `~/Projects/EMI/EMI-Backend`: `codex/bible-verse-notes` at `c257fd1ec762e009fb0764571561010f306ee3ce` (`Add local MarianMT translation service`); upstream: none. Remote: `gitea` (`https://git.reynafamily.com/adolforeyna/EMI-Backend.git`), fetch refspec `+refs/heads/*:refs/remotes/gitea/*`.
- Production checkout `aeroreyna@192.168.68.119:~/EMI-Backend`: `master` at `92320c9c8993308172282d6ac4437e19c752650a` (`Add monthly MongoDB backup script`); upstream: `origin/master`. Remote: `origin` (`http://192.168.68.119:3000/adolforeyna/EMI-Backend.git`), fetch refspec `+refs/heads/*:refs/remotes/origin/*`.
- Both commits are one-child descendants of common ancestor `65a4178e2b1491117ddb9e1b8a5ed7b53c4b5be3`; neither checkout contains the other tip object. Therefore committed code has diverged, not a simple ahead/behind relationship.
- Gitea read-only advertised `master` is `65a4178e…`; it does not advertise the Mac-mini tip or production tip. Thus neither current checkout tip is established as a remotely published latest branch tip.
- From the common ancestor, Mac-mini committed changes are: modified `.gitignore`, `README.md`, `docker-compose.yml`, `utils/chatTranslation.js`; added `translation-service/.dockerignore`, `translation-service/Dockerfile`, `translation-service/requirements.txt`, `translation-service/server.py`.
- From the common ancestor, production committed changes are: modified `.gitignore`; added `scripts/monthlyMongoBackup.sh`. The two committed `.gitignore` blobs differ. Production `docker-compose.yml` is unchanged in its committed tree; Mac-mini’s committed tree modifies it.
## Local WIP
- Mac mini has no staged changes; it has three unstaged tracked changes (`config/cookiesOptions.js`, `config/corsOptions.js`, `index.js`) and one untracked `.DS_Store`. This WIP is uncommitted and is separate from `c257fd1…`.
- Production checkout also has uncommitted state: unstaged `docker-compose.yml` and untracked `update.sh`; contents were intentionally not inspected. This is not part of production’s committed-code comparison.
## Runtime/container relationship
- The running container is `emi-backend-app-1` (`e9355e13bf21…`), image `emi-backend-app` / `sha256:0f245f65…`, running since `2026-08-17T21:20:23Z`; command is `node index.js` with workdir `/app`.
- `/app` is a read-write bind mount of `/home/aeroreyna/EMI-Backend`; `/app/node_modules` is separately volume-mounted. Therefore the running application files are served directly from the production checkout rather than from an immutable image copy.
- Runtime and checkout SHA-256 values match for `index.js`, `config/cookiesOptions.js`, and `config/corsOptions.js` (including the currently uncommitted checkout state). Git is not installed in the container, so an in-container Git revision could not be read; the bind mount plus matching file hashes establish the relevant application-file match.
## Verdict
Production is **diverged** from the latest available Mac-mini committed code, with additional uncommitted WIP on both checkouts; it is not safe to call production simply behind or ahead.
Minimal next decision required before any server update: select one explicit approved release commit/branch and decide how the production checkout’s dirty `docker-compose.yml` must be preserved or reconciled.
@@ -0,0 +1,66 @@
# EMI read-only discovery — 2026-08-18
Scope: manifest/git/runtime/Paseo inspection only. No dependency installation, source/configuration changes, service actions, or secrets access.
## Verified mapping
| Host | Checkout | Git head / branch | Registered Paseo workspace |
|---|---|---|---|
| Mac mini `.102` | `~/Projects/EMI/expoApp` | `4e26cc3` / `master` | `wks_f013c2c89410419b` — `EMI · Expo App — Main Checkout` |
| Mac mini `.102` | `~/Projects/EMI/website` | `d329c0c` / `master` | `wks_baf03fce83b6b3b7` — `EMI · Website — Main Checkout` |
| Mac mini `.102` | `~/Projects/EMI/EMI-Backend` | `c257fd1` / `codex/bible-verse-notes` | `wks_740a1fe0494b5cc9` — `EMI · Backend — Mac mini Checkout` |
| EMI server `.119` | `~/EMI-Backend` (`/home/aeroreyna/EMI-Backend`) | `92320c9` / `master` | `wks_fc39b6c9d2ebc9e0` — `EMI · Backend Production Checkout` |
All four are registered as local/main-checkout workspaces, not isolated worktrees. No `paseo.json` exists in any inspected root. The Mac mini daemon is running/reachable on loopback; providers reported available: Codex, OpenCode, pi, hermes. On `.119`, the daemon is running/reachable on `127.0.0.1:6767`; available providers are Codex, OpenCode, and pi (Claude/copilot unavailable).
## Declared candidate commands (not executed)
Confidence means that the command is explicitly declared by the manifest, not that it is safe, hermetic, or passing.
| Repository | Candidate command | Purpose | Confidence |
|---|---|---|---|
| expoApp | `npm start` | Expo dev server | High |
| expoApp | `npm run web` | Expo web dev server | High |
| expoApp | `npm run ios` / `npm run android` | native development/run | High |
| expoApp | No manifest lint, typecheck, test, or production-build script | — | High absence finding |
| website | `npm run lint` | Vue CLI lint; command sets `NODE_OPTIONS=--openssl-legacy-provider` | High |
| website | `npm run build` | Vue CLI production build; same Node option | High |
| website | `npm run serve` | development server on port 8080 | High |
| website | No manifest test or typecheck script | — | High absence finding |
| Mac mini backend | `npm run dev` | `node --watch index.js` development process | High |
| Mac mini backend | `npm start` | `node index.js` | High |
| Mac mini backend | `npm test` | declared `npx mocha test/auth.test.js` | High command / medium execution confidence: environment and test data were not examined |
| Mac mini backend | No manifest lint, typecheck, or build script | — | High absence finding |
| `.119` backend | same `npm run dev`, `npm start`, and `npm test` declarations | source checkout commands only | High declaration / low direct-host execution confidence: non-login SSH PATH has no `node`/`npm`; runtime is containerized |
| `.119` runtime | `curl --head --max-time 5 http://127.0.0.1:3001/` | reachability probe, not authenticated API health | High; executed: HTTP 302 to `/login` |
Each Node repository has `package-lock.json`; no yarn/pnpm lockfile was found. No `tsconfig.json` or `jsconfig.json` was found in any root, so no typecheck command is evidenced. The backend has `docker-compose.yml` and `test/auth.test.js`; the local app and website have no compose manifest.
## Local-change protection
- expoApp is dirty: modified `Views/PrayerTimer.js`, `components/PrayerTracker.js`, `i18nMessages.js`, `package.json`; untracked `ios/`. Remotes: `gitea`, `origin`.
- website is clean. Remote: `origin`.
- Mac mini backend is dirty: modified `config/cookiesOptions.js`, `config/corsOptions.js`, `index.js`; untracked `.DS_Store`. Remote: `gitea` only (no `origin`).
- `.119` backend is dirty: modified `docker-compose.yml`; untracked `update.sh`. Remote: `origin`.
Do not create a worktree from, reset, stash, clean, or dispatch an editing agent into any dirty checkout until the owner identifies and protects those changes. The existing workspaces point directly at those checkouts.
## `.119` runtime, service, and deployment facts
- Docker is the active system service. Container `emi-backend-app-1` (image `emi-backend-app`) has been up about five hours and publishes `0.0.0.0:3001` and `[::]:3001` to container port 3001.
- Host port 3001 is listening publicly on IPv4 and IPv6. The root probe returned `302 Found`, Express-powered, redirecting to `/login`; this confirms listener/reverse-route behavior only, not application health, authentication, dependencies, or database connectivity.
- `node index.js` is running in the backend container. The checkout's compose file exists, but it was not read because it is locally modified and may contain deployment-sensitive configuration.
- A user-managed Paseo daemon and supervisor are running. The CLI works after placing the discovered NVM Node path on `PATH`; its initial non-login SSH invocation failed only because that PATH was absent.
- Unknown: authoritative deployment/update procedure; relation of `/home/aeroreyna/EMI-Backend` to the running container (bind mount versus image build); compose project/working directory; image provenance; rollback procedure; authenticated/API health endpoint; database dependency health; expected Node version; and whether untracked `update.sh` is the intended release mechanism.
## Human review required before `paseo.json` or worktree/agent setup
1. Confirm ownership/disposition of every listed local modification and untracked path, especially `.119` `docker-compose.yml` and `update.sh`.
2. Select one repository and bounded goal; main-checkout workspaces are not writable task targets. Approve an isolated worktree location and branch policy for that repository.
3. Review the repository-specific command contract rather than inventing missing lint/typecheck/test/build steps; decide whether existing commands may access external services or mutate data.
4. For `.119`, verify the deployment source-to-container relationship, named deployment executor, health endpoint, rollback procedure, and a separately approved production boundary before any agent/worktree or `paseo.json` work.
5. Approve provider choice and required permissions; no provider/workspace/agent state was changed in this lane.
## Proposed next bounded task
Human-approved, read-only backend release-path audit on `.119`: inspect only non-secret Docker/compose metadata and container mount/image metadata to establish checkout-to-container provenance, deployment command, health endpoint, and rollback evidence; write one update to this record and make no runtime changes.
+68
View File
@@ -0,0 +1,68 @@
---
project_key: emi
status: active
factory_maturity: discovery
updated: 2026-08-17
---
# EMI — Project Definition
## Purpose
EMI is the cross-server ministry application and web/services collection: mobile/client work, website work, backend/API operations, ministry integrations, and the related human approval/deployment process.
## Execution map
| Host | Repository / service | Paseo-project role | Status |
|---|---|---|---|
| Mac mini `.102` | `~/Projects/EMI/expoApp` | `EMI · Expo App` | Registered local workspace `wks_f013c2c89410419b`; local changes exist |
| Mac mini `.102` | `~/Projects/EMI/website` | `EMI · Website` | Registered local workspace `wks_baf03fce83b6b3b7` |
| Mac mini `.102` | `~/Projects/EMI/EMI-Backend` | `EMI · Backend (Mac mini)` for local/reproduction work | Registered local workspace `wks_740a1fe0494b5cc9`; local changes exist and no `origin` is configured |
| EMI server `.119` | `~/EMI-Backend`, production API documented at `:3001` | `EMI · Backend Production` | Registered local workspace `wks_fc39b6c9d2ebc9e0`; daemon healthy on loopback; OpenCode detected; runtime, health command, deployment procedure, and Ollama Cloud provider setup remain to be discovered |
The parent `~/Projects/EMI` directory is a collection, not a source-changing Paseo project.
## External infrastructure boundary
- `api.emmint.com` is routed by the **FamReynaServer `.110` Caddy** instance to the EMI backend service on `.119`.
- This EMI project may document the dependency and verify its observed behavior, but it does **not** own or modify the FamReynaServer Caddy route, Authentik, DNS, firewall, or shared reverse-proxy policy.
- Any Caddy/proxy change belongs to the shared FamReyna infrastructure owner and requires a separately scoped, explicitly approved infrastructure task. EMI release work must treat that route as an external dependency and coordinate through evidence, not mutate it.
## Personas
- Planner: read-only repo/service discovery and task plan.
- Expo / web / backend implementer: isolated worktree only.
- Verifier: repo-specific scripts and integration evidence.
- Reviewer: independent diff, security, API/migration, and scope review.
- Release steward: prepare rollout/rollback evidence.
- Deployment executor: one named, explicitly approved production action only.
- Health monitor: read-only, change-only reporting.
## Safety boundaries
- Preserve existing local modifications before creating worktrees.
- No merge, deploy, restart, credential change, or public publishing without explicit human approval.
- Do not dispatch production backend tasks until `.119` checkout path, service manager, health command, and rollback procedure are verified.
- A cross-server change has separate Mac mini and `.119` workspaces; it is never one shared workspace.
## Active factory coordination
- **Feature / incident:** production reconciliation and release-branch convergence — **completed through push, then deployed manually by explicit approval**.
- **Coordinator session:** Factory profile session `20260818_102513_1346d3`, titled `emi: production reconciliation` and pinned for continuity. It exposed a follow-through gap: its interactive process exited after worker dispatch. The factory policy now requires interactive/resumable dispatch-and-follow-through, explicit agent IDs, and terminal-state monitoring.
- **Reconciled repository revision:** production `master` and `origin/master` are `4c1afea` (`chore(prod): preserve production compose settings`), following rebased translation commit `c257fd1` and backup-script commit `44988df`.
- **Deployment:** app and translation Compose services were rebuilt/recreated from `4c1afea`; a pre-update rollback image is retained as `emi-backend-app:pre-4c1afea-20260818T190206Z`. No Caddy, Authentik, DNS, or firewall changes were made.
- **Next active feature:** `emi: local translation production readiness`. **Execution owner: factory profile only.** The default/personal Hermes conversation may relay your instructions and report evidence, but it must not perform direct repository, server, Docker, Git, or Paseo actions for this project. Treat the current MarianMT service as WIP until its internal network path, health/readiness, functional translations, model-cache behavior, failure handling, and resource limits are verified.
## Factory readiness next actions
1. Read-only discovery of each Mac mini repository's scripts, tests, build commands, and current worktree state.
2. Read-only discovery on `.119` of the deployed checkout, runtime, service manager, health endpoint, and release procedure.
3. Register repo-specific local Paseo workspaces only after discovery review.
4. Add repo-specific `paseo.json` contracts; do not copy a generic template.
## Related records
- `emi-read-only-discovery-2026-08-18.md` — completed first factory experiment; commands and release-path unknowns
- `../paseo_software_factory_working_model_2026-08-17.md`
- `../latin_america_emi_collaboration_2026.md`
- `../../areas/operations/services_inventory.md`
+45
View File
@@ -0,0 +1,45 @@
---
project_key: family-voice
status: active
factory_maturity: discovery
updated: 2026-08-17
---
# Family Voice — Project Definition
## Purpose
Family Voice covers the privacy-first local voice-context and speaker-identification prototype, with future device integration only after offline evaluation and explicit consent decisions.
## Execution map
| Host / target | Repository / service | Paseo-project role | Status |
|---|---|---|---|
| Mac mini `.102` | `~/Projects/voice-speaker-id` | `Family Voice · Speaker ID` | Registered local workspace `wks_42151868896725e9` on `main`; offline CLI-only prototype |
| ESP32 / iPhone devices | audio input sources | Project assets, not Paseo hosts | No always-listening deployment is approved |
## Personas
- Privacy planner: evaluates scope, consent, retention, and data boundaries.
- ML experimenter: isolated code work without raw-audio export.
- Evaluation verifier: runs reproducible offline scoring/evaluation only.
- Privacy/security reviewer: checks data handling, authorization claims, and accidental cloud transmission.
- Device integration planner: design-only until explicit device approval.
## Safety boundaries
- Cached clips are never treated as approved enrollment data by filename alone.
- Do not upload raw audio, commit recordings/embeddings, create a listener, modify firmware, or enable always-listening capture without explicit approval.
- Speaker recognition must never be the sole authority for high-impact actions.
## Factory readiness next actions
1. Confirm repository checks and ignored-data boundaries.
2. Register the local repository workspace.
3. Define an evaluation-only Paseo contract.
4. Run no automated collection/deployment schedule until consent, retention, and calibration decisions are documented.
## Related records
- `../family_voice_context_and_speaker_id_2026.md`
- `../../areas/operations/services_inventory.md`
@@ -0,0 +1,34 @@
flowchart LR
classDef confirmed fill:#123d2d,stroke:#34d399,color:#e2e8f0,stroke-width:2px;
classDef inferred fill:#46351a,stroke:#fbbf24,color:#fef3c7,stroke-width:2px,stroke-dasharray: 6 4;
classDef unknown fill:#1e293b,stroke:#94a3b8,color:#e2e8f0,stroke-width:2px,stroke-dasharray: 2 4;
classDef blocked fill:#3f1d2b,stroke:#fb7185,color:#ffe4e6,stroke-width:2px;
subgraph Device[Candidate Tactility board]
PV[PipecatVoice external ELF<br/>16 kHz PCM + protocol-v1]:::confirmed
RB[ReynaBot external ELF<br/>separate legacy endpoint]:::inferred
CFG[Persisted config.json<br/>may override PipecatVoice default]:::unknown
end
subgraph Mac[Mac mini — current voice hosts]
AD[LAN voice adapter<br/>protocol-v1 WebSocket · port 8644]:::confirmed
HG[Default Hermes gateway<br/>listening · port 8642]:::confirmed
PC[Pipecat SmallWebRTC bot<br/>listening · port 7860]:::confirmed
TS[Pipecat turn/STT/TTS experiments<br/>repo: pipecat-voice-gateway]:::inferred
end
subgraph Pi[AeroPi5 — Kids Hermes runtime]
KG[hermes-gateway-kids.service<br/>kids profile · active]:::confirmed
KP[Voice route / listener / profile binding<br/>not observed in discovery]:::unknown
end
PV -->|CONFIRMED: current source default<br/>protocol-v1 WS| AD
CFG -.->|UNKNOWN: runtime override<br/>must reconcile| PV
RB -.->|INFERRED: direct legacy WS<br/>endpoint differs from PipecatVoice| HG
AD -.->|INFERRED: may call voice processing<br/>contract not yet traced live| TS
TS -.->|INFERRED: Hermes API use in source| HG
PC -.->|NOT PRODUCT PATH: WebRTC route<br/>external ELF is a documented NO-GO| PV
KG -.->|UNKNOWN: no confirmed voice transport<br/>binding to current client/adapter| AD
KG -.->|UNKNOWN: policy/runtime relationship| HG
NOTE[Status key:<br/>solid green = confirmed now<br/>dashed amber = inferred from source/history<br/>dotted gray = unknown; needs evidence<br/>rose = blocked/no-go]:::unknown
Binary file not shown.
@@ -0,0 +1,51 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1500" height="1030" viewBox="0 0 1500 1030" role="img" aria-labelledby="title desc">
<title id="title">Kids Hermes Voice — verified system design</title>
<desc id="desc">System design overview of the candidate Tactility board, Mac mini voice adapter, Pipecat path, default Hermes gateway, and AeroPi5 kids runtime. Connections are marked confirmed, inferred, or unknown.</desc>
<defs>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse"><path d="M40 0H0V40" fill="none" stroke="#1e293b" stroke-width="0.5"/></pattern>
<marker id="green" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"><path d="M0,0 L0,6 L9,3 z" fill="#34d399"/></marker>
<marker id="amber" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"><path d="M0,0 L0,6 L9,3 z" fill="#fbbf24"/></marker>
<marker id="gray" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"><path d="M0,0 L0,6 L9,3 z" fill="#94a3b8"/></marker>
<style>
.title{font:700 25px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#f8fafc}.sub{font:13px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#94a3b8}.group{font:700 14px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#cbd5e1}.name{font:700 15px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#f8fafc}.text{font:12px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#cbd5e1}.small{font:11px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#94a3b8}.label{font:11px ui-monospace,SFMono-Regular,Menlo,monospace;fill:#e2e8f0}.confirmed{fill:#123d2d;stroke:#34d399;stroke-width:2}.inferred{fill:#46351a;stroke:#fbbf24;stroke-width:2;stroke-dasharray:7 5}.unknown{fill:#1e293b;stroke:#94a3b8;stroke-width:2;stroke-dasharray:3 5}.nogood{fill:#3f1d2b;stroke:#fb7185;stroke-width:2}.boundary{fill:#0f172a;fill-opacity:.72;stroke:#475569;stroke-width:1.4;stroke-dasharray:8 5}.lineC{stroke:#34d399;stroke-width:3;fill:none;marker-end:url(#green)}.lineI{stroke:#fbbf24;stroke-width:2.5;fill:none;stroke-dasharray:8 5;marker-end:url(#amber)}.lineU{stroke:#94a3b8;stroke-width:2;fill:none;stroke-dasharray:3 6;marker-end:url(#gray)}
</style>
</defs>
<rect width="1500" height="1030" fill="#020617"/><rect width="1500" height="1030" fill="url(#grid)"/>
<text x="55" y="55" class="title">KIDS HERMES VOICE — SYSTEM DESIGN</text><text x="55" y="80" class="sub">Read-only baseline · connections show current evidence, not authorization to change or deploy</text>
<!-- boundaries -->
<rect x="50" y="125" width="360" height="650" rx="14" class="boundary"/><text x="75" y="155" class="group">CANDIDATE TACTILITY BOARD</text>
<rect x="520" y="125" width="535" height="650" rx="14" class="boundary"/><text x="545" y="155" class="group">MAC MINI — CURRENT VOICE HOSTS</text>
<rect x="1165" y="125" width="285" height="650" rx="14" class="boundary"/><text x="1190" y="155" class="group">AEROPI5 — KIDS RUNTIME</text>
<!-- flows behind boxes -->
<path d="M390 300 C450 300 465 300 540 300" class="lineC"/><text x="422" y="284" class="label">CONFIRMED · protocol-v1 WS</text>
<path d="M360 501 C452 501 466 501 540 475" class="lineI"/><text x="405" y="487" class="label">INFERRED · legacy direct WS</text>
<path d="M345 650 C430 650 440 650 540 650" class="lineU"/><text x="395" y="635" class="label">UNKNOWN · config override</text>
<path d="M750 365 C750 405 750 420 750 450" class="lineI"/><text x="765" y="412" class="label">INFERRED · processing link</text>
<path d="M850 510 C890 500 910 475 920 410" class="lineI"/><text x="870" y="455" class="label">INFERRED · Hermes API</text>
<path d="M730 690 C630 720 505 715 390 690" class="lineI"/><text x="510" y="742" class="label">NO-GO: SmallWebRTC in current external ELF</text>
<path d="M1165 330 C1100 330 1085 330 1035 330" class="lineU"/><text x="1060" y="314" class="label">UNKNOWN policy/transport binding</text>
<path d="M1165 570 C1100 570 1080 570 940 570" class="lineU"/><text x="1010" y="554" class="label">UNKNOWN</text>
<!-- device boxes -->
<rect x="75" y="230" width="315" height="130" rx="8" class="confirmed"/><text x="96" y="260" class="name">PipecatVoice app</text><text x="96" y="287" class="text">Tactility external ELF</text><text x="96" y="310" class="text">16 kHz PCM + protocol-v1 state machine</text><text x="96" y="337" class="small">Current source target: Mac mini voice adapter</text>
<rect x="75" y="430" width="285" height="125" rx="8" class="inferred"/><text x="96" y="460" class="name">ReynaBot app</text><text x="96" y="487" class="text">Separate legacy voice endpoint</text><text x="96" y="510" class="small">Endpoint differs from PipecatVoice</text><text x="96" y="532" class="small">Live use / target identity: unverified</text>
<rect x="75" y="610" width="270" height="100" rx="8" class="unknown"/><text x="96" y="640" class="name">Persisted config.json</text><text x="96" y="668" class="text">Can override non-secret endpoint</text><text x="96" y="692" class="small">Not yet read from candidate board</text>
<!-- mac boxes -->
<rect x="540" y="230" width="390" height="135" rx="8" class="confirmed"/><text x="565" y="260" class="name">LAN voice adapter</text><text x="565" y="288" class="text">protocol-v1 WebSocket · LAN-only bind</text><text x="565" y="312" class="text">Path: /api/esp32/voice/ws</text><text x="565" y="340" class="small">Confirmed listening; HTTP probe requested WS upgrade</text>
<rect x="540" y="450" width="390" height="110" rx="8" class="inferred"/><text x="565" y="480" class="name">Pipecat voice processing</text><text x="565" y="507" class="text">STT / turn service / TTS experiments</text><text x="565" y="535" class="small">Integration contract to adapter not live-traced</text>
<rect x="540" y="610" width="390" height="105" rx="8" class="confirmed"/><text x="565" y="640" class="name">Pipecat SmallWebRTC bot</text><text x="565" y="667" class="text">Service is listening</text><text x="565" y="692" class="small">Available path; not a supported current Tactility ELF route</text>
<rect x="940" y="385" width="92" height="110" rx="8" class="confirmed"/><text x="952" y="414" class="name">Default</text><text x="952" y="438" class="name">Hermes</text><text x="952" y="462" class="name">gateway</text><text x="952" y="483" class="small">listening</text>
<!-- pi box -->
<rect x="1190" y="230" width="230" height="140" rx="8" class="confirmed"/><text x="1210" y="260" class="name">Kids Hermes runtime</text><text x="1210" y="288" class="text">hermes-gateway-kids.service</text><text x="1210" y="313" class="text">active · kids profile</text><text x="1210" y="343" class="small">Policy/runtime owner</text>
<rect x="1190" y="510" width="230" height="120" rx="8" class="unknown"/><text x="1210" y="540" class="name">Voice-route binding</text><text x="1210" y="568" class="text">No current listener observed</text><text x="1210" y="594" class="small">Connection to adapter/client unknown</text>
<!-- legend and evidence -->
<rect x="50" y="815" width="1400" height="165" rx="12" fill="#0f172a" stroke="#334155" stroke-width="1.5"/>
<text x="75" y="846" class="group">EVIDENCE KEY</text><line x1="75" y1="872" x2="130" y2="872" class="lineC"/><text x="145" y="877" class="text">Confirmed now: process/listener, active service, or current source endpoint</text><line x1="610" y1="872" x2="665" y2="872" class="lineI"/><text x="680" y="877" class="text">Inferred: source/history exists; end-to-end linkage not proven</text><line x1="1110" y1="872" x2="1165" y2="872" class="lineU"/><text x="1180" y="877" class="text">Unknown: requires evidence</text>
<text x="75" y="915" class="text">Sources: current Tactility app source/README; Mac mini listener and process inspection; AeroPi5 systemd inspection; PipecatVoice postmortem; factory record.</text>
<text x="75" y="944" class="text">Current restore gate: reconcile the candidate board’s persisted PipecatVoice config against the confirmed Mac mini adapter endpoint. No source, service, or device changes were made.</text>
</svg>

After

Width:  |  Height:  |  Size: 7.9 KiB

+105
View File
@@ -0,0 +1,105 @@
---
project_key: kids-hermes-voice
status: active
factory_maturity: discovery
updated: 2026-08-18
---
# Kids Hermes Voice — Project Definition
## Purpose
Kids Hermes Voice is the child-safe, local voice experience spanning the Tactility ESP32 client, the voice-gateway application, and the Hermes kids/voice runtime. It is distinct from `family-voice`, which remains the evaluation-only speaker-identification and privacy research project. Speaker identification may later supply non-authoritative context to this project only after an explicit consent decision.
## Execution map
| Host / target | Repository / service | Paseo-project role | Current evidence |
|---|---|---|---|
| Mac mini `.102` | `~/Projects/electronics/tactility/tactility_apps` — `Apps/PipecatVoice` / related `ReynaBot` paths | `Kids Hermes Voice · Tactility client` | Repository is present on `main`, ahead of `origin/main` by 1 commit, with existing modified/untracked voice-related work; preserve it until inventoried. Existing Tactility Apps workspace: `wks_c488f281bcb459c7` (registration must be rechecked before dispatch). |
| Mac mini `.102` | `~/Projects/pipecat-voice-gateway` | `Kids Hermes Voice · Gateway` | Repository is present on `main`, with existing modified/untracked gateway work; no reset, commit, or deployment is authorized. Workspace registration still needs discovery. |
| AeroPi5 `.126` | Hermes kids/voice runtime and legacy voice-host role | `Kids Hermes Voice · Runtime` | Host was reachable on 2026-08-18. Exact checkout, active service ownership, and current configuration are unverified; read-only discovery only. |
| Tactility ESP32 fleet | First target board must be named per task | Deployment target, not a Paseo host | No install, flash, or runtime change is authorized by this record. |
## Architecture boundary
```text
Tactility voice client <-> voice-gateway protocol <-> Hermes kids/voice runtime
device UX transport child-safe response policy
```
- The client owns capture, playback, device UI, and protocol compatibility.
- The gateway owns the versioned voice transport, capability negotiation, turn telemetry, and compatibility fallbacks.
- The Hermes runtime owns the child-safe profile, permitted tools, and local response routing.
- `family-voice` owns offline speaker-ID evaluation and privacy review; it is not an authentication mechanism.
## Personas
- Integration planner: maps protocol, repository boundaries, and acceptance criteria; read-only.
- Tactility client implementer: isolated worktree only.
- Gateway/runtime implementer: isolated worktree only; never edits both repositories in one shared checkout.
- Build/protocol verifier: reports exact commands and outcomes without source fixes.
- Child-safety/privacy reviewer: checks profile/tool boundary, retention, and no-cloud/raw-audio claims.
- Device QA/deployment executor: acts only for a named device after explicit approval, rollback plan, and compatible SDK/firmware verification.
## Safety boundaries
- Do not expose administrator/system tools to child-facing sessions.
- Do not upload, commit, or place raw audio, embeddings, credentials, or pairing material in project records.
- No always-listening capture, enrollment, firmware flash, device install, daemon restart, gateway deployment, profile/permission change, or service reconfiguration without explicit human approval.
- Existing dirty worktrees are evidence to inventory, not permission to reset, commit, merge, or overwrite.
- Every source-changing lane uses one isolated worktree and an explicitly `auto-review` Paseo coding session; planners/reviewers remain read-only.
## First coordination task — baseline contract and inventory
**Goal:** establish an implementation-ready, evidence-backed baseline without changing source or devices.
**Incident context:** this voice path reportedly worked previously but has not been restored for an extended period. Treat the current effort as a restoration investigation: establish the last known working boundaries and concrete present blockers before proposing a change.
**Acceptance criteria:**
1. Identify the intended first device/board and its current firmware/SDK compatibility.
2. Inventory existing uncommitted client and gateway work by file and behavioral intent; classify it as preserve, superseded, or candidate for the first worktree.
3. Confirm the live runtime host, checkout/service owner, and the current kids/voice entry route on AeroPi5.
4. Produce a versioned client↔gateway protocol contract covering capability negotiation, PCM-first streamed output, state/error events, interruption behavior, and the full-WAV/base64 fallback.
5. Name the first source-changing milestone and its repository owner; no coding until the human approves that scope.
**Allowed now:** read-only repository, workspace, host, and device discovery; protocol planning; build-command discovery.
**Required evidence:** exact git/workspace status; repository `AGENTS.md`; runtime/service ownership; device identity plus firmware/SDK version; proposed contract location and verification commands.
**Forbidden effects:** source edits, commits, resets, installs, flashes, starts/stops/restarts, profile/permission changes, external sends, credentials, and raw-audio collection/export.
**Approval gate:** explicit human approval is required before dispatching an implementation agent, changing source, or interacting with a device/runtime.
## Baseline findings — 2026-08-18
- The canonical device architecture is **protocol-v1 LAN WebSocket**, not Pipecat SmallWebRTC inside a Tactility external ELF. The latter is a documented no-go for the current SDK/firmware boundary.
- The Mac mini currently has a live LAN adapter at `192.168.68.102:8644`, serving `/api/esp32/voice/ws`; a non-mutating HTTP probe correctly received `400` requesting a WebSocket upgrade. The default Hermes gateway separately listens on `*:8642`.
- Current Tactility `PipecatVoice` source and README agree on the `.102:8644` adapter endpoint, but prior restoration evidence refers to a different endpoint. The first gate is therefore endpoint plus persisted-device-config reconciliation, not a transport redesign.
- AeroPi5 has an active `hermes-gateway-kids.service` running the `kids` profile from `~/.hermes/profiles/kids`. It has no Paseo CLI/workspace registration, and no `:8642` listener was observed in this discovery; it is a runtime-policy dependency, not the current LAN adapter host.
- Board `.129` is reachable and its dashboard API returned HTTP `200`; board `.112` responds to ICMP but its dashboard port `80` was unavailable. `.129` is the evidence-backed candidate for the first restoration validation, pending the human naming it as the approved target.
- The local client protocol test passed (`voice_protocol tests passed`) and both involved working trees passed `git diff --check`. This is static evidence only; it does not prove a board WebSocket session, upstream PCM, speaker playback, reconnect, or STT/Hermes/TTS.
- Existing gateway/client modifications must be inventoried and retained. A credential-bearing source artifact was encountered during read-only inspection; it must be remediated in an explicitly approved, secret-safe source-change lane and must never be copied into records, logs, or chat.
## Canonical project layout
```text
Kids Hermes Voice (cross-project record)
├── Tactility client: tactility_apps/Apps/PipecatVoice
│ └── device capture/playback, protocol-v1 state machine, persisted non-secret endpoint
├── LAN adapter: voice-assistant/hermes-esp32-voice-gateway
│ └── 192.168.68.102:8644 protocol boundary, LAN framing/limits, deterministic audio fixtures
├── Voice processing: pipecat-voice-gateway
│ └── STT/TTS/turn-service experimentation; never silently substitutes for the adapter contract
└── Kids runtime: AeroPi5 ~/.hermes profile `kids`
└── child-safe policy and allowed-tool boundary; distinct from transport ownership
```
The next read-only deliverable is an endpoint/persisted-config reconciliation report for the approved board. Only after that evidence exists may a separate, approved worktree lane define the smallest restoration edit.
## Related records
- `family-voice.md`
- `tactility.md`
- `../tactility_voice_gateway_elato_transition_2026.md`
- `../voice_dev_infrastructure_2026.md`
- `../../areas/operations/services_inventory.md`
+46
View File
@@ -0,0 +1,46 @@
---
project_key: remarkable-hermes
status: active
factory_maturity: discovery
updated: 2026-08-17
---
# reMarkable Hermes Communication — Project Definition
## Purpose
reMarkable Hermes is the multi-host Paper Pro communication and watcher effort: a tablet-side Hermes surface, safe handwriting/document interaction, and the supporting logger/bridge infrastructure.
## Execution map
| Host / target | Repository / service | Paseo-project role | Status |
|---|---|---|---|
| iMac `.124` | Paper Pro SDK / cross-compile work documented under `~/remarkable-dev` | `reMarkable · App` | Exact repository path and daemon recovery still require discovery |
| AeroPi5 `.126` | watcher/logger/UDP listener history | `reMarkable · Watcher` | Inventory reports watcher not working; ownership and files need discovery |
| Paper Pro `.132` | sidecar and custom app target | Target environment, not a Paseo host | Explicit device safety controls apply |
## Personas
- App planner and Qt implementer: scoped app/worktree development.
- Watcher incident triager: read-only service inspection first.
- Watcher implementer and service verifier: only after root cause and task scope.
- Device deployment verifier: checks the specific approved artifact on-device.
- Deployment executor: performs an explicitly approved device-side action with rollback plan.
## Safety boundaries
- Do not restart xochitl, alter device system files, overwrite documents, or deploy a tablet app without explicit approval and rollback path.
- Treat the Paper Pro as a target environment, never as a generic remote coding host.
- Preserve handwritten source material and avoid bulk document manipulation.
## Factory readiness next actions
1. Discover the active iMac repository/workspace, build command, and Paseo daemon recovery path.
2. Discover current Pi watcher ownership, files, logs, and failure mode without modifications.
3. Register host-local Paseo workspaces only after that evidence is reviewed.
4. Pilot a read-only watcher triage or local app build—never a tablet deployment.
## Related records
- `../remarkable_hermes_communication_app.md`
- `../../areas/operations/services_inventory.md`
+44
View File
@@ -0,0 +1,44 @@
---
project_key: reyna-cli
status: active
factory_maturity: discovery
updated: 2026-08-17
---
# Reyna CLI — Project Definition
## Purpose
Reyna CLI is the private Mac mini operations platform for privacy-sensitive Apple integrations, family operations, and controlled local/LAN service capabilities.
## Execution map
| Host | Repository / service | Paseo-project role | Status |
|---|---|---|---|
| Mac mini `.102` | `~/Projects/platform/reyna-cli` (symlinked/known as `~/Projects/reyna-cli`), Gitea `adolforeyna/reyna-cli` | `Reyna CLI · Main` | Registered local workspace `wks_5d711dc3ed4df37e`; local ignored/untracked device artifacts exist |
## Personas
- Planner: maps requested capability to privacy and system boundaries.
- Privacy-boundary implementer: isolated worktree code changes only.
- Test verifier: runs exact CLI/unit/integration checks.
- Security reviewer: checks command injection, secret handling, permissions, network exposure, and unintended Apple-data access.
- Release steward and deployment executor: separate, approval-gated roles.
## Safety boundaries
- TCC permissions, Apple data, credentials, LaunchAgents, gateway configuration, and LAN listener exposure are separate approval boundaries.
- Never use a source-changing agent in the shared `main` checkout.
- Do not include data from Calendar, Contacts, Notes, Reminders, or authentication stores in agent prompts or brain records.
## Factory readiness next actions
1. Discover the repository's actual test/build/lint commands.
2. Register a local main-checkout Paseo workspace after checking the current local state.
3. Establish `paseo.json` with only audited, non-publishing commands.
4. Pilot a low-risk worktree change before scheduling quality automation.
## Related records
- `../reyna_cli_browser_control.md`
- `../../areas/operations/services_inventory.md`
+47
View File
@@ -0,0 +1,47 @@
---
project_key: tactility
status: active
factory_maturity: discovery
updated: 2026-08-17
---
# Tactility — Project Definition
## Purpose
Tactility is the ESP32 platform and runtime-app collection for family displays, audio, media, device interfaces, and approved hardware experiments.
## Execution map
| Host / target | Repository / service | Paseo-project role | Status |
|---|---|---|---|
| Mac mini `.102` | `~/Projects/electronics/tactility/tactility`, Gitea origin | `Tactility · Platform` | Registered local workspace `wks_f6a631c20313f1a8` on `main` |
| Mac mini `.102` | `~/Projects/electronics/tactility/tactility_apps`, Gitea origin | `Tactility · Apps` | Registered local workspace `wks_c488f281bcb459c7` on `main`; detailed app build/deploy guidance is in repo `AGENTS.md` |
| ESP32 fleet | Boards such as `.112`, `.111`, `.123` | Target environments, not Paseo hosts | Device health/version must be verified per task |
## Personas
- Firmware/app planner: read-only, identifies board/SDK/app compatibility.
- Platform or app implementer: isolated worktree only.
- Build verifier: confirms build plus undefined-symbol check.
- Hardware reviewer: assesses firmware/device risk and deployment prerequisites.
- Device QA: captures approved behavioral/screenshot evidence after deployment.
- Deployment executor: performs a specific approved device install/run only.
## Safety boundaries
- Build success alone is not completion.
- Hardware deployment requires explicit approval, named board, compatible SDK/firmware, rollback/recovery plan, and behavior verification.
- Do not blindly flash firmware, mass-install apps, or assume a remembered IP/device identity.
## Factory readiness next actions
1. Discover project-specific build/test commands for platform and apps.
2. Register two separate Mac mini Paseo workspaces.
3. Create repository-specific Paseo script contracts.
4. Pilot an app-only worktree change with build + symbol verification, without device installation.
## Related records
- `../tactility_voice_gateway_elato_transition_2026.md`
- `../../areas/operations/services_inventory.md`