Split long page text into 1500-char chunks before calling Ollama, then
mean-pool the per-chunk vectors into one page vector. Removes the hard
6000-char slice that still caused 500s on dense markdown/table pages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add position column to pages (migration 020), update listBySpace to ORDER BY position, title,
expose position in update(), add to patchSchema, and replace the space view flat table with a
tree renderer grouping pages by parent_id under h4 section headers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CF Access multi-aud: CF_ACCESS_AUD now accepts a comma-separated
allow-list so requests through either the void.hynesy.com or
void2-app.hynesy.com CF Access app are honoured as owner. Fails
closed; unlisted auds rejected. Adds multi-aud test.
Void 1 (CT 301) becomes legacy but stays running untouched as an
instant rollback. -alpha tag kept pending owner sign-off.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sidebar: Spaces / Agents / Navigate sections, accent pill on active item, status
dots on agents. Settings Agents rows expand to show the agent's persona (soul) +
capabilities/scopes via GET /api/agents/:id/profile.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summarises the Homelab Monitor (CT300 :8080) into a blackflame card: Claude Code
token usage today/week + top model, and OpenClaw/Ollama p50/p95 latency + error rate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
clock/weather etc. default to 1/6 width; sizes store an integer span 1-12
(legacy s/m/l still accepted by /api/dashboard/layout).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A cryptographically-verified CF Access JWT (signature vs team JWKS + audience +
email allow-list) now counts as the owner, so browser requests through the CF
tunnel don't need the owner token copied onto each device. Fails closed → owner
token remains the fallback (LAN-direct + dev/tests unaffected). Opt-in via
CF_ACCESS_TEAM_DOMAIN / CF_ACCESS_AUD / CF_ACCESS_OWNER_EMAILS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Q3: prod void DB role NOSUPERUSER (vector marked trusted; deploy/README documents it)
- Q4: buildChildEnv allow-list for the claude subprocess (no OWNER_TOKEN/DATABASE_URL/secrets leak)
- Q5: pending-change approve claims-before-applying + reopens on failure (no re-approvable dup)
- Q6: /capture/upload validates space_id (UUID+existence); pg pool statement_timeout 30s
- Q9: disabled failing syncoid-donatello timer on Z
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses final-review findings: I1 render-generation guard prevents a double-mount
/timer leak on rapid re-navigation; I2 adds anonymous-rejection tests for the owner-only
POST /speedtest/run and /health/check; M1 CSS comment; M2 cron↔worker dedup note;
M4 full 8-byte PNG signature check; M5 card-contract unit test for all 7 cards.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds GET /api/health/services returning registry services grouped by
category with merged cached status and per-group healthy counts, and
POST /api/health/check (owner-only) that enqueues a health.check
pg-boss job. Registers the health_check worker in the jobs index.
- migration 011_yerin.sql: seed read-only 'yerin' agent ({read:true}, kind claude,
model NULL = server default; switch to local Ollama via agents.model anytime)
- companion-stdio.js: select the toolset from VOID_TOOL_REGISTRY ('security' →
Yerin's securityRegistry; default → Dross's companionRegistry)
- tests/mcp/registry_select.test.js
Remaining for Yerin (left for review): an entry point (route or cron) + persona
prompt — see docs/yerin-security-agent.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three more read-only tools on securityRegistry:
- pending_review: agent-proposed changes awaiting approval (injection surface)
- resource_exposure: host/url/status attack-surface inventory (resources.listExposure,
scalar cols only — no monitoring/metadata/credentials)
- token_audit: token label/last_used/revoked, never the hash
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
verifyToken loaded every non-revoked token and bcrypt-compared each (O(n) per
request — auth-latency DoS + linear scaling). New token format
vk_<selector>.<verifier>: the non-secret selector is indexed and locates exactly
one row; only the verifier is bcrypt-hashed. Legacy NULL-selector tokens still
verify via a fallback scan. Dropped the useless idx_agent_tokens_hash.
- migration 010_token_selector.sql (adds selector col + unique partial index)
- createToken/verifyToken reworked; also adds listTokenMeta (read for Yerin's
token_audit tool)
- tests/repos/token_selector.test.js
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- pool.js: add pool.on('error') handler — an idle-client error (DB restart /
.215 failover) previously crashed the process (no 'error' listener → throw)
- context tool: project a SAFE_COLUMNS allow-list for resources (never the
monitoring/metadata JSON blobs); also add 'resource' to TABLE (was unhandled)
- applyPendingChange: guard the 'upsert' arm so a non-upsertable entity_type
fails with a clear ValidationError instead of a bare TypeError
Tests: pool_error, context (resource case), pending_extended_actions (guard).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New securityRegistry (separate from companionRegistry) with two read-only,
secret-free tools for the Yerin security agent:
- audit_log: query the redacted audit trail by actor_kind/actor_id
- agent_inventory: list agents + capabilities/scopes (explicit projection,
never SELECT *, no token material)
Follows the existing createRegistry() pattern. Design + wiring roadmap in
docs/yerin-security-agent.md. Not yet seeded/exposed over MCP (left for review).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Owner bearer token was compared with === / !==, which short-circuits on the
first differing byte and leaks token length+prefix via response timing
(security-sweep-2026-06-01.md). New timingSafeStrEqual (crypto.timingSafeEqual
with a length pre-check so it never throws on length mismatch); wired into both
owner.js and agent_auth.js.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The pending_changes.action CHECK only permitted create/update/delete, so a
suggest-tier agent hitting POST /api/refs/upsert (or the resource dependency
routes) 500'd on the INSERT (docs/security-followups.md HIGH finding).
- migration 009: widen CHECK to include 'upsert'
- applyPendingChange: dispatch 'upsert' -> refsRepo.upsertByExternal on approve
- resources.js: add_dependency/remove_dependency are now owner-only (requireOwner),
infra wiring is never diverted to pending_changes
- tests/api/pending_extended_actions.test.js: regression coverage
Full suite green (278 pass / 1 skip).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- system prompt = Dross (Ozriel's construct fragment, per Void 1.0), with tool guidance
- migration 008 renames the seeded agent 'companion' → display name 'Dross'
- removed lib/ai/anthropic.js + lib/ai/agent/runtime.js + tests + @anthropic-ai/sdk dep (companion now runs via the claude CLI; kept lib/ai/secret.js for the Vaultwarden roadmap)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>