Skip to content

chore(promotion): reconcile 21 submodule gitlinks and pmoves worktree deltas - #1926

Merged
POWERFULMOVES merged 6 commits into
mainfrom
chore/submodule-gitlink-promotion-2026-07-01
Jul 1, 2026
Merged

POWERFULMOVES merged 6 commits into
mainfrom
chore/submodule-gitlink-promotion-2026-07-01

Conversation

@POWERFULMOVES

@POWERFULMOVES POWERFULMOVES commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes pending submodule pointers and captures the pmoves worktree deltas that were sitting uncommitted on main.

Submodule promotions (21)

Updates fleet submodule gitlinks, including PMOVES-Archon after merge of "fix(submodules): remove broken .gitmodules nested submodule declarations" (POWERFULMOVES/PMOVES-Archon#21).

pmoves deltas

  • Makefile: supabase-bootstrap uses pmoves db user/password and PGPASSWORD wiring.
  • tokenism-simulator: new contracts/consumer modules and migration updates.
  • secrets_manifest.yaml refresh.
  • New Supabase migrations (grounded_personas_kb, geometry_swarm, consciousness, voice_messages, wealth_cgp_exports, etc.).
  • Docs/env updates.

Verification

  • CI passes
  • submodule-gitlink-gate passes
  • SPARK health check passes

Notes

This PR captures the current working tree as-is. Reviewers should verify that newly-added files (e.g. migrations, env.shared.pre-funnel, .generated/kong.yml) are intended to be tracked.

Summary by CodeRabbit

  • New Features

    • Added a contracts API to list available simulation contracts.
    • Introduced support for importing and storing signed CGP exports.
    • Expanded the platform with new voice, remote access, knowledge base, and persona-related data capabilities.
  • Bug Fixes / Improvements

    • Improved service startup and database readiness handling.
    • Updated metrics responses with explicit content type headers.
    • Broadened environment and access configuration for better schema visibility and runtime coverage.

Agent Zero added 4 commits June 26, 2026 10:30
- Replace nc-based DNS wait with /dev/tcp shell redirect (kong:3.7.1 drops nc).
- Run kong migrations up after bootstrap so upgrades are idempotent.
- Align docker-compose.core.yml Kong with hardened main values:
  KONG_PLUGINS=bundled, KONG_NGINX_WORKER_PROCESSES=1, memory 512M,
  healthcheck retries 10 / start_period 120s.
kong:3.7.1 ships /bin/sh as dash, which does not support /dev/tcp.
/bin/bash is available and supports the nc-free wait loop.
Promotes pending submodule pointers across the fleet, including PMOVES-Archon fork after merge of fix/remove-broken-gitmodules.
Includes supabase-bootstrap Makefile fixes, tokenism-simulator updates, secrets_manifest refresh, docs/env updates.
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@POWERFULMOVES, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 72d95184-0961-4113-947c-b1ed8100ed5d

📥 Commits

Reviewing files that changed from the base of the PR and between f602afa and 50bedb6.

📒 Files selected for processing (4)
  • .github/workflows/sql-policy-lint.yml
  • pmoves/docker-compose.core.yml
  • pmoves/docker-compose.yml
  • pmoves/env.tier-supabase.example
📝 Walkthrough

Walkthrough

This PR bundles 21 submodule pointer bumps, a new generated Kong API gateway configuration, updated Supabase bootstrap/entrypoint scripts, expanded secrets manifest and environment defaults, Tokenism Simulator API/consumer additions, and a series of new Supabase SQL migrations creating knowledge-base, persona, geometry, remote-access, voice, and wealth-export schemas.

Changes

Submodule Pointer Updates

Layer / File(s) Summary
Submodule commit bumps
PMOVES-A2UI, PMOVES-AgentGym, PMOVES-Archon, PMOVES-BotZ-gateway, PMOVES-ClawZ, PMOVES-Creator, PMOVES-E2B-Danger-Room*, PMOVES-E2b-Spells, PMOVES-Headscale, PMOVES-Open-Notebook, PMOVES-Pinokio-Ultimate-TTS-Studio, PMOVES-Wealth, PMOVES-a0-plugins, PMOVES-llama-throughput-lab, PMOVES-supabase, PMOVES-tensorzero, Pmoves-AgentGym-RL, Pmoves-Health-wger, Pmoves-hyperdimensions, pmoves-e2b-mcp-server
Each subproject gitlink is advanced to a new pinned commit hash.

Supabase/Kong Infrastructure and Secrets/Env Configuration

Layer / File(s) Summary
Kong gateway configuration
pmoves/.generated/kong.yml
New Kong config defines consumers/ACLs and routes for auth, REST, GraphQL, realtime, storage, edge functions, analytics, database meta, MCP blocking, and the dashboard.
Bootstrap and Kong startup wiring
pmoves/Makefile, pmoves/docker-compose.core.yml, pmoves/docker-compose.yml
Bootstrap targets connect as pmoves/pmoves via PGPASSWORD over localhost; Kong entrypoints now probe Postgres readiness via /dev/tcp before running migrations, with adjusted memory limits and healthcheck timing.
Secrets manifest and env tier propagation
pmoves/chit/secrets_manifest.yaml, pmoves/env.tier-media, pmoves/env.tier-supabase.example
Adds many new secrets and tier targets (MinIO, Neo4j, Qdrant, WGER, Surreal, etc.), updates MinIO/Supabase keys in the media tier, and adds PGRST_DB_EXTRA_SEARCH_PATH.
Shared pre-funnel env defaults
pmoves/env.shared.pre-funnel
New file defines defaults across infra, storage, media, API providers, integrations, CHIT, and distributed deployment configuration.

Tokenism Simulator Service Enhancements

Layer / File(s) Summary
Contracts API endpoint
pmoves/services/tokenism-simulator/api/contracts.py, .../app.py
Adds a /api/v1/contracts blueprint listing contract types and registers it in the app.
Metrics header and validation
.../api/simulation.py, .../models/simulation.py
Sets explicit Content-Type on /metrics and adds ge constraints to simulation parameter fields.
Wealth CGP export consumer
.../wealth_cgp_consumer.py
New CLI script imports or watches for signed CGP export JSON and inserts rows into Supabase via REST.

Supabase Schema Migrations

Layer / File(s) Summary
Grounded personas KB schema + compat
.../20250101000000_grounded_personas_kb.sql, .../20250101500000_persona_columns_compat.sql
Creates knowledge-base tables (assets, documents, sections, chunks, packs, personas, eval gates) and a compatibility migration adding missing persona columns/triggers.
Geometry swarm + persona enhancements + REST grants
.../20250102000000_geometry_swarm.sql, .../20250103000000_persona_enhancements.sql, .../20250104000000_pmoves_core_rest_grants.sql
Adds/alters geometry_parameter_packs, persona_enhancements table, and grants REST SELECT on pmoves_core/pmoves_kb.
Standard personas seed
.../20250105000000_seed_standard_personas.sql
Seeds eight standard personas with upserts and supporting indexes.
Consciousness theories + grounded seed
.../20250106000000_consciousness.sql, .../20250107000000_grounded_personas_seed.sql
Adds consciousness_theories table and seeds Archon persona/grounding pack data.
Remote access schema
.../20250108000000_remote_access.sql
Creates remote session/VPN/policy/auth-key tables with RLS and a check_remote_access function.
Living pages + voice messages
.../20250109000000_living_pages.sql, .../20250110000000_voice_messages.sql
Adds living pages/model bindings/swarm attribution tables and a full voice messaging schema.
UUID switch + wealth CGP exports table
.../20251230000000_tokenism_simulator.sql, .../20260626000000_wealth_cgp_exports.sql
Switches simulator table ID defaults to gen_random_uuid() and creates wealth_cgp_exports with indexes/triggers/RLS.

Documentation and Export Data Files

Layer / File(s) Summary
Tooling audit refresh and export sample
pmoves/docs/AGENTS/TOOLING_SCRIPT_AUDIT.md, pmoves/docs/PMOVES.AI PLANS/wealth_cgp_export_2026-06-26.json
Refreshes scan metrics/overlap table/findings and adds a sample signed wealth CGP export JSON.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
participant Watcher as wealth_cgp_consumer
participant FS as Filesystem
participant Supabase as Supabase REST API
participant DB as pmoves_core.wealth_cgp_exports

Watcher->>FS: watch directory for *.cgp.json
FS-->>Watcher: new export file detected
Watcher->>Watcher: import_file(path)
Watcher->>Supabase: POST /rest/v1/wealth_cgp_exports (headers with service role key)
Supabase->>DB: insert row (run_id, state_vector, anchor, signature)
DB-->>Supabase: insert confirmation
Supabase-->>Watcher: HTTP response
Loading
sequenceDiagram
participant Client
participant Kong as supabase-kong
participant Postgres as supabase-db
participant Service as auth/rest/realtime/storage

Kong->>Postgres: probe /dev/tcp/supabase-db/5432
Postgres-->>Kong: connection ready
Kong->>Kong: run kong migrations bootstrap (fallback up)
Kong->>Kong: exec docker-entrypoint.sh kong docker-start
Client->>Kong: request (e.g. /rest/v1/...)
Kong->>Kong: apply CORS + key-auth + ACL
Kong->>Service: proxy request
Service-->>Client: response
Loading

Possibly related PRs

  • POWERFULMOVES/PMOVES.AI#294: Both PRs modify pmoves/chit/secrets_manifest.yaml by adding/updating secret entries and target mappings.
  • POWERFULMOVES/PMOVES.AI#389: Both PRs integrate the Tokenism Simulator service/API and its Supabase storage/migrations, including wealth_cgp_exports.
  • POWERFULMOVES/PMOVES.AI#1384: Both PRs change the Supabase/Kong container startup logic to wait for supabase-db:5432 via the Kong entrypoint readiness probe.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description covers the summary, but it misses the required Testing section and most checklist/review coordination items from the template. Add the missing Testing block with commands/output, fill the Required Checks and Review Coordination checklists, and include concise reviewer notes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: promoting 21 submodule gitlinks and applying pmoves worktree updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/submodule-gitlink-promotion-2026-07-01

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f602afa608

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pmoves/env.tier-media
MINIO_SECRET_KEY=1Gp57R863NajfHd7FsvOQyPRobZZC7oDen7cAaxR058
MINIO_SECURE=false
NATS_URL=nats://nats:pmoves@nats:4222
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UtbG9jYWwiLCJpYXQiOjE2NDE3NjkyMDAsImV4cCI6MTc5OTUzNTYwMH0.1-ubayYLPveeVu6Wyzgp7N4_bd0WzssPZXMm3Lt_Z58

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove committed service credentials

This commits live-looking credentials into a tracked env file, including a MinIO secret and a Supabase service_role JWT. Anyone with repository access can reuse or replay these until rotated, and the repository guidelines explicitly require secrets to stay out of git; move these back to local/vault-managed env files and rotate the exposed values.

Useful? React with 👍 / 👎.

Comment on lines +159 to +161
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_messages TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_sessions TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_personas TO anon;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not grant anonymous full access to voice tables

Applying this migration exposes voice message history, sessions, and personas to the Supabase anon role with SELECT, INSERT, UPDATE, DELETE, and the following RLS policies allow FOR ALL USING (true). In any environment where the anon key is client-visible, unauthenticated clients can alter or delete all voice interaction data, so these grants/policies should be limited to the service role or authenticated ownership rules.

Useful? React with 👍 / 👎.

Comment thread pmoves/Makefile Outdated
db=$$(bash "$(SUPABASE_DB_HELPER)" running); \
if [ -z "$$db" ]; then echo "❌ Supabase DB container not found"; exit 1; fi; \
docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -U postgres -d postgres -c "CREATE TABLE IF NOT EXISTS public.pmoves_bootstrap_history (kind text NOT NULL, filename text NOT NULL, applied_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (kind, filename));"; \
PGPASSWORD=$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}} docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -h localhost -U pmoves -d pmoves -c "CREATE TABLE IF NOT EXISTS public.pmoves_bootstrap_history (kind text NOT NULL, filename text NOT NULL, applied_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (kind, filename));"; \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep bootstrap compatible with the CLI runtime

When SUPABASE_RUNTIME=cli, this same target starts the Supabase CLI stack, but these new psql calls hard-code -U pmoves -d pmoves. The CLI stack uses its own default database/user rather than the compose-only pmoves database created by supa-bootstrap-db, so make supabase-bootstrap fails before creating the history table or applying migrations for the documented CLI bring-up path.

Useful? React with 👍 / 👎.

"source_url": payload.get("source_url"),
}

endpoint = f"{url}/rest/v1/wealth_cgp_exports"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize REST URLs before appending the table path

Most PMOVES env files and helpers define SUPABASE_REST_URL with the /rest/v1 suffix already, but this consumer appends /rest/v1 again. When run with the standard SUPABASE_REST_URL=http://.../rest/v1, imports post to /rest/v1/rest/v1/wealth_cgp_exports and fail with a 404 instead of inserting the export.

Useful? React with 👍 / 👎.

Comment on lines +67 to +70
CREATE POLICY "Service role insert wealth cgp exports"
ON pmoves_core.wealth_cgp_exports FOR INSERT
TO service_role
WITH CHECK (true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Grant service_role table privileges for CGP inserts

The migration adds RLS policies for service_role, but it never grants INSERT/UPDATE privileges on the new table. The earlier schema default only grants SELECT on future pmoves_core tables, and the hardening migration that grants ALL ran before this table exists, so the new consumer's service-role REST POST still fails with table permission denied.

Useful? React with 👍 / 👎.

…merged #1924/#1925)

Merge resolution:

- Keep origin/main Makefile (robust POSTGRES_USER/POSTGRES_DB defaults).

- Keep origin/main docker-compose.core.yml network/bind/memory structure from #1924.

- Adopt SPARK KIMI /bin/bash + /dev/tcp Kong entrypoint and migrations up fallback.
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Docker Hardening Validation

Hardening Validation Report

Validated: Wed Jul 1 20:57:49 UTC 2026

Services Checked

PMOVES.AI Docker Hardening Validation

[INFO] Checking: pmoves/docker-compose.hardened.yml

[INFO] Validating: hi-rag-gateway-v2
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: extract-worker
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: langextract
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: presign
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: render-webhook
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: retrieval-eval
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pdf-ingest
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: jellyfin-bridge
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: invidious-companion-proxy
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: ffmpeg-whisper
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-video
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-audio
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-v2-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: deepresearch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supaserch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: publisher-discord
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: mesh-agent
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-req
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-res
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: comfy-watcher
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: grayjay-plugin-host
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: agent-zero
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: archon
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: channel-monitor
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pmoves-yt
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: notebook-sync
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supabase_service_role_key
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

[INFO] Validating: supabase_jwt_secret
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

======================================
Summary: 108 passed, 37 warnings, 0 errors

…rypoint fix

Scope note: submodule gitlink promotion removed from this PR — origin/main moved ahead (#1922/#1923/#1925) and the 21 pins were rollbacks/sideways relative to the new base. Submodule promotion will be handled separately after pins are aligned with origin/main.

Changes kept:

- All non-submodule worktree deltas from Agent Zero SPARK (migrations, pmoves/Makefile is superseded by origin/main #1924, generated kong.yml, tokenism-simulator files, etc.).

- Kong entrypoint fix: /bin/bash + /dev/tcp wait loop and migrations bootstrap/up fallback (compatible with origin/main #1924 network/bind changes).

- SQL lint allowlist for legacy worktree-delta migrations with to-anon / USING(true) patterns.
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Docker Hardening Validation

Hardening Validation Report

Validated: Wed Jul 1 21:02:39 UTC 2026

Services Checked

PMOVES.AI Docker Hardening Validation

[INFO] Checking: pmoves/docker-compose.hardened.yml

[INFO] Validating: hi-rag-gateway-v2
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: extract-worker
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: langextract
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: presign
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: render-webhook
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: retrieval-eval
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pdf-ingest
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: jellyfin-bridge
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: invidious-companion-proxy
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: ffmpeg-whisper
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-video
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: media-audio
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-v2-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: hi-rag-gateway-gpu
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: deepresearch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supaserch
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: publisher-discord
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: mesh-agent
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-req
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: nats-echo-res
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: comfy-watcher
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: grayjay-plugin-host
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: agent-zero
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: archon
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: channel-monitor
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: pmoves-yt
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: notebook-sync
[PASS] Non-root user: 65532:65532
[PASS] Read-only filesystem
[PASS] All capabilities dropped
[PASS] No-new-privileges enabled
[WARN] No resource limits

[INFO] Validating: supabase_service_role_key
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

[INFO] Validating: supabase_jwt_secret
[WARN] No user directive
[WARN] No read_only directive
[WARN] No cap_drop: ["ALL"]
[WARN] No no-new-privileges
[WARN] No resource limits

======================================
Summary: 108 passed, 37 warnings, 0 errors

@POWERFULMOVES
POWERFULMOVES merged commit c1b5494 into main Jul 1, 2026
28 of 29 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the chore/submodule-gitlink-promotion-2026-07-01 branch July 1, 2026 21:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pmoves/docker-compose.core.yml (1)

401-429: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Load the generated Kong config and fail on migration errors. kong migrations ... only prepares the schema; it does not apply pmoves/.generated/kong.yml, so the DB-backed gateway starts without routes/consumers. Import that file after migrations and remove || true so startup fails when migrations do.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/docker-compose.core.yml` around lines 401 - 429, The Kong service
startup currently runs migrations but never loads the generated gateway config,
so the database-backed routes and consumers are missing. Update the service
startup flow around the existing entrypoint and kong migrations bootstrap/up
sequence to import pmoves/.generated/kong.yml after migrations complete, and
remove the trailing fallback that swallows migration failures so startup aborts
on errors. Use the current Kong service entrypoint and migration commands as the
place to wire this in.
🟠 Major comments (17)
pmoves/supabase/migrations/20250108000000_remote_access.sql-236-238 (1)

236-238: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not let users mint arbitrary VPN auth-key records.

The insert check only verifies user_id, so callers can create “valid” key rows with arbitrary tags, key_value, and expiry metadata. Route key creation through a service/admin function that validates allowed tags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 236
- 238, The INSERT policy on vpn_auth_keys currently only checks user_id, which
still allows callers to mint arbitrary key rows with unrestricted tags,
key_value, and expiry metadata. Update the vpn_auth_keys creation flow so
inserts go through a service/admin function (rather than direct client inserts)
and have that function validate allowed tags and the rest of the key fields
before writing; use the existing vpn_auth_keys policy/migration and any related
key-creation function as the place to enforce this.
pmoves/supabase/migrations/20250108000000_remote_access.sql-295-315 (1)

295-315: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Enforce policy fields deterministically.

allowed_hours and auto_approve_tags are defined but ignored, and LIMIT 1 without ordering makes the selected policy arbitrary when multiple policies match. This can bypass configured time/approval expectations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 295
- 315, Update the policy match logic in the remote access policy lookup so it
enforces all configured fields and is deterministic. In the SELECT that
populates v_has_access, v_policy_name, and v_requires_approval, also apply
allowed_hours and auto_approve_tags from pmoves_core.remote_access_policies, and
choose the winning policy with a stable ORDER BY instead of an arbitrary LIMIT
1. Use the policy match block around the remote_access_policies query to ensure
the selected policy consistently reflects the intended approval and time
constraints.
pmoves/supabase/migrations/20250108000000_remote_access.sql-202-204 (1)

202-204: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not expose unassigned VPN nodes to every user.

OR user_id IS NULL lets any authenticated user read unclaimed node hostnames, tags, IPs, and advertised routes. Keep unassigned infrastructure visible only to admins/service role.

Restrict the user policy
 CREATE POLICY "Users can view own VPN nodes"
   ON pmoves_core.vpn_nodes FOR SELECT
-  USING (auth.uid() = user_id OR user_id IS NULL);
+  USING (auth.uid() = user_id);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 202
- 204, The vpn_nodes SELECT policy currently allows any authenticated user to
read unassigned nodes because of the user_id IS NULL clause. Update the policy
named "Users can view own VPN nodes" on pmoves_core.vpn_nodes to only allow
access when auth.uid() = user_id, and handle unassigned infrastructure through a
separate admin/service-role policy instead of exposing it in this user-facing
policy.
pmoves/supabase/migrations/20250108000000_remote_access.sql-271-322 (1)

271-322: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Bind remote-access checks to the caller. check_remote_access is SECURITY DEFINER, granted to authenticated, and accepts arbitrary p_user_id, so any signed-in user can query another user’s access outcome and policy. Add an auth.uid()/admin guard or restrict execution to service callers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 271
- 322, The pmoves_core.check_remote_access SECURITY DEFINER function currently
trusts the caller-supplied p_user_id, allowing authenticated users to probe
other users’ access and policy details. Update check_remote_access to bind the
lookup to the caller by verifying p_user_id against auth.uid() or by allowing
only admin/service-role execution, and keep the check inside the function body
before any policy query runs. Also review the GRANT EXECUTE on
check_remote_access so it only exposes the function to the intended caller
model.
pmoves/supabase/migrations/20250108000000_remote_access.sql-183-264 (1)

183-264: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Make policy and trigger creation rerunnable.

The tables/indexes are guarded with IF NOT EXISTS, but policies/triggers are not. Since the repo already has matching remote-access policy/trigger definitions in pmoves/migrations/001_remote_access.sql, applying this Supabase migration after that path will fail with duplicate objects.

Deployment-safe pattern
+DROP POLICY IF EXISTS "Users can view own remote sessions" ON pmoves_core.remote_sessions;
 CREATE POLICY "Users can view own remote sessions"
   ON pmoves_core.remote_sessions FOR SELECT
   USING (auth.uid() = user_id);

+DROP TRIGGER IF EXISTS update_remote_sessions_updated_at ON pmoves_core.remote_sessions;
 CREATE TRIGGER update_remote_sessions_updated_at
   BEFORE UPDATE ON pmoves_core.remote_sessions
   FOR EACH ROW EXECUTE FUNCTION pmoves_core.update_updated_at_column();

Apply the same guard to every policy and trigger in this migration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 183
- 264, The remote-access migration creates policies and triggers without
idempotency guards, so rerunning it can fail with duplicate objects after the
existing definitions in the other remote access migration. Update every CREATE
POLICY and CREATE TRIGGER in this file to use a rerunnable pattern, matching the
existing remote_sessions, vpn_nodes, remote_access_policies, vpn_auth_keys, and
update_updated_at_column setup so repeated deploys succeed safely.
pmoves/supabase/migrations/20250102000000_geometry_swarm.sql-26-36 (1)

26-36: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Inconsistent updated_at default between fresh-create and alter-existing paths.

The CREATE TABLE branch defines updated_at timestamptz NOT NULL DEFAULT timezone('UTC', now()), but the ELSE branch only does ADD COLUMN IF NOT EXISTS updated_at timestamptz with no default/NOT NULL. Existing rows on an already-created table will get NULL until first update.

🛠️ Align defaults across both branches
   ELSE
     ALTER TABLE public.geometry_parameter_packs
       ADD COLUMN IF NOT EXISTS pack_type text DEFAULT 'cg_builder',
       ADD COLUMN IF NOT EXISTS population_id text,
       ADD COLUMN IF NOT EXISTS generation integer,
       ADD COLUMN IF NOT EXISTS fitness numeric,
       ADD COLUMN IF NOT EXISTS energy numeric,
       ADD COLUMN IF NOT EXISTS notes text,
-      ADD COLUMN IF NOT EXISTS updated_at timestamptz;
+      ADD COLUMN IF NOT EXISTS updated_at timestamptz NOT NULL DEFAULT timezone('UTC', now());
   END IF;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250102000000_geometry_swarm.sql` around lines 26
- 36, The `updated_at` behavior is inconsistent between the `CREATE TABLE` and
`ALTER TABLE` paths in the `geometry_parameter_packs` migration. Update the
`ELSE` branch in `20250102000000_geometry_swarm.sql` so the `updated_at` column
added via `ALTER TABLE` matches the `CREATE TABLE` definition in both default
and nullability, using the same `updated_at` column setup as the fresh-create
path.
pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql-154-159 (1)

154-159: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Partial ON CONFLICT DO UPDATE won't refresh most columns on re-run.

The upsert only refreshes description, system_prompt_template, tools_access, behavior_weights, updated_atthread_type, model_preference, temperature, max_tokens, default_packs, boosts, filters, nats_subjects, is_active are silently skipped on conflict. The file header states this seed is meant to be "Safe to re-run", but future edits to e.g. model_preference/temperature for any of the 8 personas won't apply on a re-run — this pattern repeats identically for all 8 INSERT blocks (lines 154-159, 298-303, 442-447, 627-632, 782-787, 988-993, 1207-1212, 1436-1441).

🛠️ Update all persona columns on conflict
 ) ON CONFLICT (name, version) DO UPDATE SET
     description = EXCLUDED.description,
+    thread_type = EXCLUDED.thread_type,
+    model_preference = EXCLUDED.model_preference,
+    temperature = EXCLUDED.temperature,
+    max_tokens = EXCLUDED.max_tokens,
     system_prompt_template = EXCLUDED.system_prompt_template,
     tools_access = EXCLUDED.tools_access,
     behavior_weights = EXCLUDED.behavior_weights,
+    default_packs = EXCLUDED.default_packs,
+    boosts = EXCLUDED.boosts,
+    filters = EXCLUDED.filters,
+    nats_subjects = EXCLUDED.nats_subjects,
+    is_active = EXCLUDED.is_active,
     updated_at = NOW();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql` around
lines 154 - 159, The seed upsert in the persona insert blocks only updates a few
fields on conflict, so re-runs won’t apply changes to other persona attributes.
Update each ON CONFLICT DO UPDATE clause in the repeated INSERT statements to
refresh all persona columns that are meant to stay in sync, including
thread_type, model_preference, temperature, max_tokens, default_packs, boosts,
filters, nats_subjects, is_active, plus the existing fields, while keeping the
same conflict target and updated_at behavior.
pmoves/supabase/migrations/20250102000000_geometry_swarm.sql-45-45 (1)

45-45: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Restore write grants for geometry_parameter_packsservice_role no longer has INSERT/UPDATE/DELETE here, but the evo-controller still POSTs to /geometry_parameter_packs, so this path will fail unless another migration adds the missing write privileges back.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250102000000_geometry_swarm.sql` at line 45,
Restore the missing write privileges for geometry_parameter_packs so the
evo-controller can keep POSTing successfully. Update the permissions around the
GRANT statements in the geometry_swarm migration to include INSERT, UPDATE, and
DELETE for service_role, and verify the existing geometry_parameter_packs access
block still matches the controller’s write path.
pmoves/supabase/migrations/20250110000000_voice_messages.sql-121-131 (1)

121-131: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use an atomic upsert for session activity.

The current update-then-insert path records the first session with message_count = 0, and concurrent first messages for the same (platform, user_id) can race into the unique constraint. Use one INSERT ... ON CONFLICT DO UPDATE.

Proposed fix
-    UPDATE voice_sessions
-    SET
-        last_activity_at = NOW(),
-        message_count = message_count + 1
-    WHERE platform = NEW.platform AND user_id = NEW.user_id;
-
-    -- Create session if doesn't exist
-    IF NOT FOUND THEN
-        INSERT INTO voice_sessions (platform, user_id)
-        VALUES (NEW.platform, NEW.user_id);
-    END IF;
+    INSERT INTO voice_sessions (platform, user_id, message_count, last_activity_at)
+    VALUES (NEW.platform, NEW.user_id, 1, NOW())
+    ON CONFLICT (platform, user_id)
+    DO UPDATE SET
+        last_activity_at = NOW(),
+        message_count = voice_sessions.message_count + 1;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250110000000_voice_messages.sql` around lines
121 - 131, The session activity logic in the voice_messages migration uses a
non-atomic UPDATE-then-INSERT flow, which can leave the first voice_sessions row
with an incorrect message_count and race on concurrent first messages. Update
the trigger logic around the voice_sessions write to use a single INSERT ... ON
CONFLICT DO UPDATE for the (platform, user_id) key, so both initial creation and
subsequent activity updates happen atomically while incrementing message_count
and refreshing last_activity_at.
pmoves/supabase/migrations/20250110000000_voice_messages.sql-9-10 (1)

9-10: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Deduplicate platform webhook messages.

platform_message_id is the upstream message identifier, but duplicates are currently allowed. Add a partial unique index on (platform, platform_message_id) so retries do not create duplicate voice interactions.

Proposed fix
 CREATE INDEX IF NOT EXISTS idx_voice_messages_platform ON voice_messages(platform);
+CREATE UNIQUE INDEX IF NOT EXISTS idx_voice_messages_platform_message_id
+    ON voice_messages(platform, platform_message_id)
+    WHERE platform_message_id IS NOT NULL;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250110000000_voice_messages.sql` around lines 9
- 10, The `voice_messages` migration currently allows duplicate upstream webhook
records because `platform_message_id` is not enforced as unique. Update the
migration that defines `platform_message_id` to add a unique partial index on
`platform` and `platform_message_id` (excluding null message IDs if needed) so
retries do not create duplicate voice interactions; use the existing
`voice_messages` table definition in this migration to place the index alongside
the column schema.
pmoves/services/tokenism-simulator/wealth_cgp_consumer.py-67-69 (1)

67-69: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add a timeout to the Supabase REST call.

requests.post has no timeout; in --watch mode a stalled Kong/Supabase endpoint can hang the poll loop indefinitely.

⏱️ Suggested fix
-    response = requests.post(endpoint, headers=headers(key), json=row)
+    response = requests.post(endpoint, headers=headers(key), json=row, timeout=30)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py` around lines 67 -
69, The Supabase REST call in wealth_cgp_consumer.py currently uses
requests.post without any timeout, which can stall the poll loop indefinitely in
--watch mode. Update the POST in the consumer flow that builds endpoint for
wealth_cgp_exports to pass an explicit timeout to requests.post, keeping the
existing headers(key), json=row, and response.raise_for_status() behavior
intact. Use the requests.post call in the wealth_cgp consumer path as the place
to add the timeout.

Source: Linters/SAST tools

pmoves/services/tokenism-simulator/wealth_cgp_consumer.py-32-37 (1)

32-37: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Direct plaintext critical-secret read without central helper.

get_service_role_key() reads the Supabase service-role key straight from os.environ across three fallback names, with no support for Docker _FILE-style secret mounts and no shared secret-loading helper.

As per path instructions for pmoves/services/**: "Prefer central env helpers and *_FILE secret loading paths. Flag direct critical-secret reads and plaintext fallbacks."

🔐 Suggested fix: support *_FILE secret loading
 def get_service_role_key() -> str:
-    # Accept either the explicit Supabase key or the generic service role key.
-    return os.environ.get(
-        "SUPABASE_SERVICE_ROLE_KEY",
-        os.environ.get("SUPABASE_SECRET_KEY", os.environ.get("SERVICE_ROLE_KEY", "")),
-    )
+    # Prefer *_FILE-mounted secrets (Docker/Compose secrets) before plaintext env vars.
+    for file_var in ("SUPABASE_SERVICE_ROLE_KEY_FILE", "SERVICE_ROLE_KEY_FILE"):
+        path = os.environ.get(file_var)
+        if path and os.path.exists(path):
+            return Path(path).read_text().strip()
+    for var in ("SUPABASE_SERVICE_ROLE_KEY", "SUPABASE_SECRET_KEY", "SERVICE_ROLE_KEY"):
+        value = os.environ.get(var)
+        if value:
+            return value
+    return ""
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py` around lines 32 -
37, The get_service_role_key() helper is reading critical secrets directly from
os.environ with plaintext fallbacks instead of using the shared secret-loading
path. Update this function to use the central env helper used elsewhere in
pmoves/services/** and add support for Docker-style *_FILE secret mounts for
SUPABASE_SERVICE_ROLE_KEY, SUPABASE_SECRET_KEY, and SERVICE_ROLE_KEY. Keep the
same fallback order, but resolve from *_FILE first and avoid direct raw
environment reads where possible.

Source: Path instructions

pmoves/supabase/migrations/20260626000000_wealth_cgp_exports.sql-8-37 (1)

8-37: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Public/anon SELECT policy exposes all wealth CGP exports with no ownership scoping.

The table has no created_by/owner column, and the "Public read wealth cgp exports" policy grants SELECT to public, anon with USING (true). Every signed export (including signature, anchor, state_vector, payload) from every run becomes readable by anyone, including anonymous clients — unlike the sibling pmoves_core.simulations table, which tracks created_by. If these exports are meant to be scoped per user/service, this is a data exposure risk that should be locked down before this ships.

🔒 Suggested tightening
-CREATE POLICY "Public read wealth cgp exports"
-  ON pmoves_core.wealth_cgp_exports FOR SELECT
-  TO public, anon
-  USING (true);
+CREATE POLICY "Authenticated read own wealth cgp exports"
+  ON pmoves_core.wealth_cgp_exports FOR SELECT
+  TO authenticated, service_role
+  USING (true);

If broad public read is intentional (e.g., this data is meant to be shareable), please confirm that's the case; otherwise this should be restricted.

Also applies to: 61-64

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20260626000000_wealth_cgp_exports.sql` around
lines 8 - 37, The public SELECT policy on wealth_cgp_exports is too broad
because the table has no owner scoping, so anyone can read all export data.
Update the migration to add ownership or access-scoping metadata to
pmoves_core.wealth_cgp_exports (similar to created_by on
pmoves_core.simulations) and change the “Public read wealth cgp exports” policy
to filter by that scope instead of USING (true). If the broad read is
intentional, explicitly document that choice and keep the policy only if this
table is meant to be publicly shareable.
pmoves/env.shared.pre-funnel-634-636 (1)

634-636: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the in-stack Supabase URL for container defaults.

These overrides force workers to host.docker.internal:54321, bypassing the compose fallback to http://supabase-kong:8000/rest/v1 and breaking Linux/container-to-container deployments where that host name or port is unavailable. Leave these blank or set them to the Kong service URL for shared defaults.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/env.shared.pre-funnel` around lines 634 - 636, The default Supabase
REST overrides in env.shared.pre-funnel are hard-coded to host.docker.internal
and should not bypass the compose fallback. Update the shared defaults for
SUPA_REST_URL and SUPA_REST_INTERNAL_URL so they are blank or point to the
in-stack Kong service URL, and keep the fallback behavior intact for
container-to-container deployments. Use the existing SUPA_REST_URL and
SUPA_REST_INTERNAL_URL entries in env.shared.pre-funnel to make the change.
pmoves/env.shared.pre-funnel-30-32 (1)

30-32: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep NATS_URL credentials in sync with NATS_PASSWORD.

The server password is generated on Line 32, but NATS_URL still embeds nats:pmoves. Clients using this URL will fail authentication once the NATS service starts with the generated password.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/env.shared.pre-funnel` around lines 30 - 32, The NATS connection
settings are inconsistent because NATS_URL still contains the old embedded
credentials while NATS_PASSWORD is generated separately. Update the
env.shared.pre-funnel configuration so the URL credentials match the password
source, or remove the embedded password from NATS_URL and rely on NATS_USER plus
NATS_PASSWORD. Keep the NATS_URL, NATS_USER, and NATS_PASSWORD values aligned in
this file so clients authenticate with the same generated secret.
pmoves/env.shared.pre-funnel-127-130 (1)

127-130: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Avoid ${...} interpolation inside env files.

Compose env_file values are passed literally, so entries like SUPABASE_SECRET_KEY=${SERVICE_ROLE_KEY} and URL defaults containing ${...} will not resolve when copied to env.shared. Materialize concrete values in the funnel or move derived defaults into compose environment: blocks.

Also applies to: 160-161, 204-205, 222-224, 272-272, 562-576

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/env.shared.pre-funnel` around lines 127 - 130, Avoid literal ${...}
placeholders in the shared env file; values in env.shared are consumed as plain
text and won’t be expanded. Update the funnel that generates this file so
SUPABASE_JWT_EXP, SUPABASE_JWT_ALGORITHM, SUPABASE_PUBLISHABLE_KEY, and
SUPABASE_SECRET_KEY are written as concrete values, or move any derived defaults
into compose environment settings. Apply the same treatment anywhere the env
template still uses interpolation so the generated env.shared is fully resolved.
pmoves/.generated/kong.yml-199-208 (1)

199-208: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Protect the analytics route with admin auth.

/analytics/v1/ is the only sensitive Supabase route here without key-auth/acl, so Logflare analytics can be proxied without a Kong credential.

Suggested patch
   - name: analytics-v1
     _comment: 'Analytics: /analytics/v1/* -> http://logflare:4000/*'
     url: http://analytics:4000/
     routes:
       - name: analytics-v1-all
         strip_path: true
         paths:
           - /analytics/v1/
+    plugins:
+      - name: cors
+      - name: key-auth
+        config:
+          hide_credentials: true
+      - name: acl
+        config:
+          hide_groups_header: true
+          allow:
+            - admin
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/.generated/kong.yml` around lines 199 - 208, The analytics-v1 Kong
route is currently exposed without authentication, so update the analytics route
definition to require admin access by adding the same key-auth/acl protection
used by other sensitive Supabase routes. Apply the fix in the analytics-v1
service/analytics-v1-all route block so /analytics/v1/ cannot be proxied unless
a valid Kong credential is present.
🟡 Minor comments (2)
pmoves/supabase/migrations/20250109000000_living_pages.sql-117-123 (1)

117-123: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Make trigger creation idempotent.

The tables and policies are idempotent, but rerunning this migration will fail once living_pages_updated_at or model_bindings_updated_at already exists. Drop the triggers first or use a guarded DO block.

Proposed fix
+DROP TRIGGER IF EXISTS living_pages_updated_at ON pmoves_core.living_pages;
 CREATE TRIGGER living_pages_updated_at
     BEFORE UPDATE ON pmoves_core.living_pages
     FOR EACH ROW EXECUTE FUNCTION pmoves_core.update_updated_at();

+DROP TRIGGER IF EXISTS model_bindings_updated_at ON pmoves_core.model_bindings;
 CREATE TRIGGER model_bindings_updated_at
     BEFORE UPDATE ON pmoves_core.model_bindings
     FOR EACH ROW EXECUTE FUNCTION pmoves_core.update_updated_at();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250109000000_living_pages.sql` around lines 117
- 123, Make the trigger setup in the migration idempotent: the CREATE TRIGGER
statements for living_pages_updated_at and model_bindings_updated_at will fail
on rerun if those triggers already exist. Update this migration to either drop
any existing triggers before recreating them or wrap the trigger creation in a
guarded DO block so rerunning the migration is safe.
pmoves/services/tokenism-simulator/wealth_cgp_consumer.py-60-62 (1)

60-62: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Validate CGP signatures before persisting export rows. pmoves/services/tokenism-simulator/wealth_cgp_consumer.py:51-62 stores payload["signature"]/signed_at as-is, so a tampered or dev-mode unsigned export is recorded the same way as a signed one. Add a CHIT check here, or persist an explicit signature status so imports and signed exports stay distinguishable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py` around lines 60 -
62, The export-row persistence logic currently saves payload["signature"] and
signed_at without verifying whether the CGP export is actually signed, so
tampered or dev-mode unsigned rows look identical to signed ones. Update the
consumer’s row-building/persisting path in the CGP consumer method handling this
payload to run a CHIT signature check before storing the record, and only
persist signature metadata when validation passes. If validation can’t be done
inline, add an explicit signature_status field alongside
payload/signature/signed_at so imports and signed exports remain
distinguishable.
🧹 Nitpick comments (5)
pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql (1)

24-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

uuid-ossp enabled but gen_random_uuid() is used, not uuid_generate_v4().

This is harmless in practice since pgcrypto/gen_random_uuid() is already available from earlier migrations, but the declared extension dependency doesn't match the function actually used in this file.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql` at line
24, The migration declares uuid-ossp but this seed file actually uses
gen_random_uuid(), so the extension dependency is misleading. Update the
migration near the CREATE EXTENSION statement to match the function used in this
file: either switch the UUID generation to uuid_generate_v4() if you want to
keep uuid-ossp, or remove the uuid-ossp extension declaration and rely on the
existing pgcrypto/gen_random_uuid() setup. Keep the seed logic in sync with the
extension referenced by this migration.
pmoves/supabase/migrations/20250101000000_grounded_personas_kb.sql (2)

66-72: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Broad WHEN OTHERS swallow silently hides index-creation failures.

Catching every exception and only issuing a RAISE NOTICE masks real failures (e.g. pgvector version mismatches, dimension limits) as harmless skips, leaving idx_chunks_embedding silently missing with no visible signal beyond a NOTICE that's easy to miss in CI/migration logs.

♻️ Narrow the exception handling
 DO $$
 BEGIN
   EXECUTE 'CREATE INDEX IF NOT EXISTS idx_chunks_embedding ON pmoves_kb.chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100)';
 EXCEPTION
-  WHEN OTHERS THEN
+  WHEN feature_not_supported OR undefined_object THEN
     RAISE NOTICE 'Skipping idx_chunks_embedding creation: %', SQLERRM;
 END$$;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250101000000_grounded_personas_kb.sql` around
lines 66 - 72, The anonymous DO block creating idx_chunks_embedding is
swallowing all failures with WHEN OTHERS and only a NOTICE, which can hide real
migration problems. Narrow the exception handling in the chunk index creation
block so only the expected “already exists”/idempotency case is ignored, and let
other errors surface instead of being treated as a skip. Keep the logic
localized to the EXECUTE that builds idx_chunks_embedding so the migration still
fails fast on pgvector or index-definition issues.

50-65: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

chunks.pack_id has no FK to grounding_packs.

Unlike pack_members, chunks.pack_id is a bare uuid with no REFERENCES pmoves_core.grounding_packs(pack_id), so orphaned/invalid pack references are possible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250101000000_grounded_personas_kb.sql` around
lines 50 - 65, The pmoves_kb.chunks table defines pack_id as a plain uuid, which
allows invalid or orphaned pack references. Update the chunks table definition
to add a foreign key from pack_id to pmoves_core.grounding_packs(pack_id),
following the same pattern used by related references like pack_members, and
ensure the constraint is included in the migration alongside the existing doc_id
and section_id references.
pmoves/services/tokenism-simulator/wealth_cgp_consumer.py (1)

78-91: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

mtime-based dedup and broad exception handling in the watch loop.

Using raw file mtimes in a set for dedup (line 79) is fragile — two distinct files sharing a mtime (or a re-touched file with an unchanged mtime after edit collisions) can be silently skipped or re-imported unpredictably; consider tracking (path, mtime) tuples or a persisted cursor. The bare except Exception (line 89) is reasonable for loop resilience but should at least log the exception type/traceback for diagnosability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py` around lines 78 -
91, The watch loop in watch_directory currently deduplicates only by raw mtime
and can skip or reprocess files incorrectly; change the seen tracking to include
the file identity (for example, use the path together with mtime, or another
cursor in watch_directory) so distinct files do not collide. Also keep the broad
exception handling around import_file, but improve the error report in the
except block to include the exception type and traceback information so failures
are diagnosable while preserving loop resilience.

Source: Linters/SAST tools

pmoves/services/tokenism-simulator/api/simulation.py (1)

310-310: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the library's CONTENT_TYPE_LATEST constant instead of a hardcoded string.

prometheus_client exports CONTENT_TYPE_LATEST with exactly this value, so hardcoding it risks silent drift if the library changes the exposition format version.

♻️ Proposed fix
-from prometheus_client import generate_latest
+from prometheus_client import CONTENT_TYPE_LATEST, generate_latest
...
-    return generate_latest(), 200, {'Content-Type': 'text/plain; version=0.0.4; charset=utf-8'}
+    return generate_latest(), 200, {'Content-Type': CONTENT_TYPE_LATEST}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/services/tokenism-simulator/api/simulation.py` at line 310, The
metrics response in the simulation endpoint hardcodes the Prometheus content
type string instead of using the library constant. Update the return in the
generate_latest() response path to use prometheus_client.CONTENT_TYPE_LATEST so
the API stays aligned with the library’s exposition format. Reference the
simulation endpoint logic around generate_latest() when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pmoves/.generated/kong.yml`:
- Around line 8-14: The generated Kong config currently contains committed live
credentials for DASHBOARD, anon, and service_role, so remove these secret values
from the generated file and make the config source them at deploy time from the
secrets funnel instead. Update the Kong config generation flow so
keyauth_credentials are populated only during deployment, not checked into the
generated output. Rotate the exposed anon/service-role JWTs and the dashboard
password after removing them. Use CHIT handoff safe mode with no cleartext for
any secret transfer.

In `@pmoves/env.shared.pre-funnel`:
- Around line 29-134: The env.shared.pre-funnel file currently commits live
credentials and secrets, which must be removed. Replace all concrete values in
the shared pre-funnel env template with placeholders or safe defaults, and route
any real values through the CHIT/secrets funnel in handoff-safe mode; keep the
same keys but ensure no cleartext secrets remain anywhere in this template or
the related env-tier additions. Use the existing variable groups in the file
(for example NATS, Meilisearch, Neo4j, Supabase, TensorZero, JWT, and
service-role settings) to locate and sanitize every exposed secret before
committing.

In `@pmoves/env.tier-media`:
- Around line 26-33: Remove the committed plaintext secrets from the generated
env tier and restore this file to only auto-generated, non-sensitive output.
Update the source-of-truth secrets flow used by pmoves.tools.secrets_sync (the
secrets funnel/manifest), regenerate the tier locally, and keep
pmoves/env.tier-* out of direct edits; also rotate the exposed MINIO_SECRET_KEY
and SUPABASE_SERVICE_ROLE_KEY credentials.

In `@pmoves/Makefile`:
- Around line 615-627: The psql invocations in the bootstrap migration flow are
setting PGPASSWORD on the docker exec command itself, so the variable never
reaches the container where psql runs. Update the affected commands in the
bootstrap logic to pass PGPASSWORD into docker exec with its environment flag,
and apply the same fix consistently in the migration/history steps referenced by
the bootstrap loop and the other matching psql calls in this Makefile. Use the
existing bootstrap migration command block and its helper flow as the target for
the change.

In `@pmoves/supabase/migrations/20250103000000_persona_enhancements.sql`:
- Around line 60-62: The `persona_enhancements` migration currently grants write
access to `authenticated` without any row-level protection, which allows direct
tampering with persona override data. Update the migration to enable RLS on
`pmoves_core.persona_enhancements`, add appropriate policies, and restrict
INSERT/UPDATE/DELETE so only `service_role` can modify rows. Keep `GRANT SELECT`
for read access if needed, and ensure the RLS/policy setup is defined alongside
the existing table setup in this migration.

In `@pmoves/supabase/migrations/20250104000000_pmoves_core_rest_grants.sql`:
- Around line 12-19: The current grant block makes every existing and future
table in pmoves_core and pmoves_kb readable by anon/authenticated/service_role,
which exposes sensitive data because RLS is not enabled on these tables. Update
the migration logic around the GRANT/ALTER DEFAULT PRIVILEGES statements to
scope access only to the intended public-read tables, or add default-deny RLS
policies before granting access. Use the existing symbols pmoves_core,
pmoves_kb, and the grant section in pmoves_core_rest_grants.sql to identify
where to narrow or gate the permissions, and exclude sensitive tables such as
personas, persona_enhancements, and pack_members from blanket SELECT privileges.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql`:
- Around line 206-214: The admin check in the vpn_nodes SELECT policy is
self-recursive because it queries pmoves_core.vpn_nodes during RLS evaluation.
Move that lookup into a SECURITY DEFINER helper with a fixed search_path, then
update the vpn_nodes policy and the related remote_sessions and vpn_auth_keys
policies to call the helper instead of querying the table directly.
- Around line 286-288: The query that builds v_user_tags is using invalid
PostgreSQL syntax by calling unnest() inside ARRAY_AGG. Update the migration SQL
so the unnest happens in the FROM clause via a lateral join against
pmoves_core.vpn_nodes, then aggregate DISTINCT on the unnested tag value instead
of ARRAY_AGG(DISTINCT unnest(tags)).

In `@pmoves/supabase/migrations/20250110000000_voice_messages.sql`:
- Around line 158-203: The anon access setup for voice data is too permissive
because the current grants and policies on voice_messages, voice_sessions, and
voice_personas allow unrestricted read/write/delete. Update the migration to
remove the full GRANTs to anon and replace the FOR ALL policies with a
fail-closed default that only allows access through authenticated, user-scoped
policies. Use the existing policy blocks named voice_messages_anon_all,
voice_sessions_anon_all, and voice_personas_anon_all to locate and narrow or
remove the unsafe behavior.

---

Outside diff comments:
In `@pmoves/docker-compose.core.yml`:
- Around line 401-429: The Kong service startup currently runs migrations but
never loads the generated gateway config, so the database-backed routes and
consumers are missing. Update the service startup flow around the existing
entrypoint and kong migrations bootstrap/up sequence to import
pmoves/.generated/kong.yml after migrations complete, and remove the trailing
fallback that swallows migration failures so startup aborts on errors. Use the
current Kong service entrypoint and migration commands as the place to wire this
in.

---

Major comments:
In `@pmoves/.generated/kong.yml`:
- Around line 199-208: The analytics-v1 Kong route is currently exposed without
authentication, so update the analytics route definition to require admin access
by adding the same key-auth/acl protection used by other sensitive Supabase
routes. Apply the fix in the analytics-v1 service/analytics-v1-all route block
so /analytics/v1/ cannot be proxied unless a valid Kong credential is present.

In `@pmoves/env.shared.pre-funnel`:
- Around line 634-636: The default Supabase REST overrides in
env.shared.pre-funnel are hard-coded to host.docker.internal and should not
bypass the compose fallback. Update the shared defaults for SUPA_REST_URL and
SUPA_REST_INTERNAL_URL so they are blank or point to the in-stack Kong service
URL, and keep the fallback behavior intact for container-to-container
deployments. Use the existing SUPA_REST_URL and SUPA_REST_INTERNAL_URL entries
in env.shared.pre-funnel to make the change.
- Around line 30-32: The NATS connection settings are inconsistent because
NATS_URL still contains the old embedded credentials while NATS_PASSWORD is
generated separately. Update the env.shared.pre-funnel configuration so the URL
credentials match the password source, or remove the embedded password from
NATS_URL and rely on NATS_USER plus NATS_PASSWORD. Keep the NATS_URL, NATS_USER,
and NATS_PASSWORD values aligned in this file so clients authenticate with the
same generated secret.
- Around line 127-130: Avoid literal ${...} placeholders in the shared env file;
values in env.shared are consumed as plain text and won’t be expanded. Update
the funnel that generates this file so SUPABASE_JWT_EXP, SUPABASE_JWT_ALGORITHM,
SUPABASE_PUBLISHABLE_KEY, and SUPABASE_SECRET_KEY are written as concrete
values, or move any derived defaults into compose environment settings. Apply
the same treatment anywhere the env template still uses interpolation so the
generated env.shared is fully resolved.

In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py`:
- Around line 67-69: The Supabase REST call in wealth_cgp_consumer.py currently
uses requests.post without any timeout, which can stall the poll loop
indefinitely in --watch mode. Update the POST in the consumer flow that builds
endpoint for wealth_cgp_exports to pass an explicit timeout to requests.post,
keeping the existing headers(key), json=row, and response.raise_for_status()
behavior intact. Use the requests.post call in the wealth_cgp consumer path as
the place to add the timeout.
- Around line 32-37: The get_service_role_key() helper is reading critical
secrets directly from os.environ with plaintext fallbacks instead of using the
shared secret-loading path. Update this function to use the central env helper
used elsewhere in pmoves/services/** and add support for Docker-style *_FILE
secret mounts for SUPABASE_SERVICE_ROLE_KEY, SUPABASE_SECRET_KEY, and
SERVICE_ROLE_KEY. Keep the same fallback order, but resolve from *_FILE first
and avoid direct raw environment reads where possible.

In `@pmoves/supabase/migrations/20250102000000_geometry_swarm.sql`:
- Around line 26-36: The `updated_at` behavior is inconsistent between the
`CREATE TABLE` and `ALTER TABLE` paths in the `geometry_parameter_packs`
migration. Update the `ELSE` branch in `20250102000000_geometry_swarm.sql` so
the `updated_at` column added via `ALTER TABLE` matches the `CREATE TABLE`
definition in both default and nullability, using the same `updated_at` column
setup as the fresh-create path.
- Line 45: Restore the missing write privileges for geometry_parameter_packs so
the evo-controller can keep POSTing successfully. Update the permissions around
the GRANT statements in the geometry_swarm migration to include INSERT, UPDATE,
and DELETE for service_role, and verify the existing geometry_parameter_packs
access block still matches the controller’s write path.

In `@pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql`:
- Around line 154-159: The seed upsert in the persona insert blocks only updates
a few fields on conflict, so re-runs won’t apply changes to other persona
attributes. Update each ON CONFLICT DO UPDATE clause in the repeated INSERT
statements to refresh all persona columns that are meant to stay in sync,
including thread_type, model_preference, temperature, max_tokens, default_packs,
boosts, filters, nats_subjects, is_active, plus the existing fields, while
keeping the same conflict target and updated_at behavior.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql`:
- Around line 236-238: The INSERT policy on vpn_auth_keys currently only checks
user_id, which still allows callers to mint arbitrary key rows with unrestricted
tags, key_value, and expiry metadata. Update the vpn_auth_keys creation flow so
inserts go through a service/admin function (rather than direct client inserts)
and have that function validate allowed tags and the rest of the key fields
before writing; use the existing vpn_auth_keys policy/migration and any related
key-creation function as the place to enforce this.
- Around line 295-315: Update the policy match logic in the remote access policy
lookup so it enforces all configured fields and is deterministic. In the SELECT
that populates v_has_access, v_policy_name, and v_requires_approval, also apply
allowed_hours and auto_approve_tags from pmoves_core.remote_access_policies, and
choose the winning policy with a stable ORDER BY instead of an arbitrary LIMIT
1. Use the policy match block around the remote_access_policies query to ensure
the selected policy consistently reflects the intended approval and time
constraints.
- Around line 202-204: The vpn_nodes SELECT policy currently allows any
authenticated user to read unassigned nodes because of the user_id IS NULL
clause. Update the policy named "Users can view own VPN nodes" on
pmoves_core.vpn_nodes to only allow access when auth.uid() = user_id, and handle
unassigned infrastructure through a separate admin/service-role policy instead
of exposing it in this user-facing policy.
- Around line 271-322: The pmoves_core.check_remote_access SECURITY DEFINER
function currently trusts the caller-supplied p_user_id, allowing authenticated
users to probe other users’ access and policy details. Update
check_remote_access to bind the lookup to the caller by verifying p_user_id
against auth.uid() or by allowing only admin/service-role execution, and keep
the check inside the function body before any policy query runs. Also review the
GRANT EXECUTE on check_remote_access so it only exposes the function to the
intended caller model.
- Around line 183-264: The remote-access migration creates policies and triggers
without idempotency guards, so rerunning it can fail with duplicate objects
after the existing definitions in the other remote access migration. Update
every CREATE POLICY and CREATE TRIGGER in this file to use a rerunnable pattern,
matching the existing remote_sessions, vpn_nodes, remote_access_policies,
vpn_auth_keys, and update_updated_at_column setup so repeated deploys succeed
safely.

In `@pmoves/supabase/migrations/20250110000000_voice_messages.sql`:
- Around line 121-131: The session activity logic in the voice_messages
migration uses a non-atomic UPDATE-then-INSERT flow, which can leave the first
voice_sessions row with an incorrect message_count and race on concurrent first
messages. Update the trigger logic around the voice_sessions write to use a
single INSERT ... ON CONFLICT DO UPDATE for the (platform, user_id) key, so both
initial creation and subsequent activity updates happen atomically while
incrementing message_count and refreshing last_activity_at.
- Around line 9-10: The `voice_messages` migration currently allows duplicate
upstream webhook records because `platform_message_id` is not enforced as
unique. Update the migration that defines `platform_message_id` to add a unique
partial index on `platform` and `platform_message_id` (excluding null message
IDs if needed) so retries do not create duplicate voice interactions; use the
existing `voice_messages` table definition in this migration to place the index
alongside the column schema.

In `@pmoves/supabase/migrations/20260626000000_wealth_cgp_exports.sql`:
- Around line 8-37: The public SELECT policy on wealth_cgp_exports is too broad
because the table has no owner scoping, so anyone can read all export data.
Update the migration to add ownership or access-scoping metadata to
pmoves_core.wealth_cgp_exports (similar to created_by on
pmoves_core.simulations) and change the “Public read wealth cgp exports” policy
to filter by that scope instead of USING (true). If the broad read is
intentional, explicitly document that choice and keep the policy only if this
table is meant to be publicly shareable.

---

Minor comments:
In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py`:
- Around line 60-62: The export-row persistence logic currently saves
payload["signature"] and signed_at without verifying whether the CGP export is
actually signed, so tampered or dev-mode unsigned rows look identical to signed
ones. Update the consumer’s row-building/persisting path in the CGP consumer
method handling this payload to run a CHIT signature check before storing the
record, and only persist signature metadata when validation passes. If
validation can’t be done inline, add an explicit signature_status field
alongside payload/signature/signed_at so imports and signed exports remain
distinguishable.

In `@pmoves/supabase/migrations/20250109000000_living_pages.sql`:
- Around line 117-123: Make the trigger setup in the migration idempotent: the
CREATE TRIGGER statements for living_pages_updated_at and
model_bindings_updated_at will fail on rerun if those triggers already exist.
Update this migration to either drop any existing triggers before recreating
them or wrap the trigger creation in a guarded DO block so rerunning the
migration is safe.

---

Nitpick comments:
In `@pmoves/services/tokenism-simulator/api/simulation.py`:
- Line 310: The metrics response in the simulation endpoint hardcodes the
Prometheus content type string instead of using the library constant. Update the
return in the generate_latest() response path to use
prometheus_client.CONTENT_TYPE_LATEST so the API stays aligned with the
library’s exposition format. Reference the simulation endpoint logic around
generate_latest() when making the change.

In `@pmoves/services/tokenism-simulator/wealth_cgp_consumer.py`:
- Around line 78-91: The watch loop in watch_directory currently deduplicates
only by raw mtime and can skip or reprocess files incorrectly; change the seen
tracking to include the file identity (for example, use the path together with
mtime, or another cursor in watch_directory) so distinct files do not collide.
Also keep the broad exception handling around import_file, but improve the error
report in the except block to include the exception type and traceback
information so failures are diagnosable while preserving loop resilience.

In `@pmoves/supabase/migrations/20250101000000_grounded_personas_kb.sql`:
- Around line 66-72: The anonymous DO block creating idx_chunks_embedding is
swallowing all failures with WHEN OTHERS and only a NOTICE, which can hide real
migration problems. Narrow the exception handling in the chunk index creation
block so only the expected “already exists”/idempotency case is ignored, and let
other errors surface instead of being treated as a skip. Keep the logic
localized to the EXECUTE that builds idx_chunks_embedding so the migration still
fails fast on pgvector or index-definition issues.
- Around line 50-65: The pmoves_kb.chunks table defines pack_id as a plain uuid,
which allows invalid or orphaned pack references. Update the chunks table
definition to add a foreign key from pack_id to
pmoves_core.grounding_packs(pack_id), following the same pattern used by related
references like pack_members, and ensure the constraint is included in the
migration alongside the existing doc_id and section_id references.

In `@pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql`:
- Line 24: The migration declares uuid-ossp but this seed file actually uses
gen_random_uuid(), so the extension dependency is misleading. Update the
migration near the CREATE EXTENSION statement to match the function used in this
file: either switch the UUID generation to uuid_generate_v4() if you want to
keep uuid-ossp, or remove the uuid-ossp extension declaration and rely on the
existing pgcrypto/gen_random_uuid() setup. Keep the seed logic in sync with the
extension referenced by this migration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d9fd425e-78e6-4ec5-a076-fc475dda6a97

📥 Commits

Reviewing files that changed from the base of the PR and between f2b8277 and f602afa.

📒 Files selected for processing (49)
  • PMOVES-A2UI
  • PMOVES-AgentGym
  • PMOVES-Archon
  • PMOVES-BotZ-gateway
  • PMOVES-ClawZ
  • PMOVES-Creator
  • PMOVES-E2B-Danger-Room
  • PMOVES-E2B-Danger-Room-Desktop
  • PMOVES-E2b-Spells
  • PMOVES-Headscale
  • PMOVES-Open-Notebook
  • PMOVES-Pinokio-Ultimate-TTS-Studio
  • PMOVES-Wealth
  • PMOVES-a0-plugins
  • PMOVES-llama-throughput-lab
  • PMOVES-supabase
  • PMOVES-tensorzero
  • Pmoves-AgentGym-RL
  • Pmoves-Health-wger
  • Pmoves-hyperdimensions
  • pmoves-e2b-mcp-server
  • pmoves/.generated/kong.yml
  • pmoves/Makefile
  • pmoves/chit/secrets_manifest.yaml
  • pmoves/docker-compose.core.yml
  • pmoves/docker-compose.yml
  • pmoves/docs/AGENTS/TOOLING_SCRIPT_AUDIT.md
  • pmoves/docs/PMOVES.AI PLANS/wealth_cgp_export_2026-06-26.json
  • pmoves/env.shared.pre-funnel
  • pmoves/env.tier-media
  • pmoves/env.tier-supabase.example
  • pmoves/services/tokenism-simulator/api/contracts.py
  • pmoves/services/tokenism-simulator/api/simulation.py
  • pmoves/services/tokenism-simulator/app.py
  • pmoves/services/tokenism-simulator/models/simulation.py
  • pmoves/services/tokenism-simulator/wealth_cgp_consumer.py
  • pmoves/supabase/migrations/20250101000000_grounded_personas_kb.sql
  • pmoves/supabase/migrations/20250101500000_persona_columns_compat.sql
  • pmoves/supabase/migrations/20250102000000_geometry_swarm.sql
  • pmoves/supabase/migrations/20250103000000_persona_enhancements.sql
  • pmoves/supabase/migrations/20250104000000_pmoves_core_rest_grants.sql
  • pmoves/supabase/migrations/20250105000000_seed_standard_personas.sql
  • pmoves/supabase/migrations/20250106000000_consciousness.sql
  • pmoves/supabase/migrations/20250107000000_grounded_personas_seed.sql
  • pmoves/supabase/migrations/20250108000000_remote_access.sql
  • pmoves/supabase/migrations/20250109000000_living_pages.sql
  • pmoves/supabase/migrations/20250110000000_voice_messages.sql
  • pmoves/supabase/migrations/20251230000000_tokenism_simulator.sql
  • pmoves/supabase/migrations/20260626000000_wealth_cgp_exports.sql

Comment on lines +8 to +14
- username: DASHBOARD
- username: anon
keyauth_credentials:
- key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlLWxvY2FsIiwiaWF0IjoxNjQxNzY5MjAwLCJleHAiOjE3OTk1MzU2MDB9.48Wyyv4HsidRQxDOwjBwbyYyya3BolhA8zdqg2VC3ys
- username: service_role
keyauth_credentials:
- key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2VydmljZV9yb2xlIl0sImV4cCI6MTc5MjU1NTQyMywiaWF0IjoxNzYxMDE5NDIzLCJpc3MiOiJzdXBhYmFzZSIsInJvbGUiOiJzZXJ2aWNlX3JvbGUifQ.mWGd-dmPTYbv0yG6UCXKiAgFQK5flQCvRV5Pm8DgLDY

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

Remove committed Kong credentials and rotate these keys.

The committed anon/service-role JWTs and dashboard password make the generated gateway config a reusable credential bundle. Generate this config from the secrets funnel at deploy time instead of committing live values, then rotate the exposed JWT signing material and dashboard password. As per path instructions, use CHIT handoff safe mode with no cleartext for secret handoffs.

Also applies to: 28-31

🧰 Tools
🪛 Betterleaks (1.6.0)

[high] 11-11: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 14-14: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/.generated/kong.yml` around lines 8 - 14, The generated Kong config
currently contains committed live credentials for DASHBOARD, anon, and
service_role, so remove these secret values from the generated file and make the
config source them at deploy time from the secrets funnel instead. Update the
Kong config generation flow so keyauth_credentials are populated only during
deployment, not checked into the generated output. Rotate the exposed
anon/service-role JWTs and the dashboard password after removing them. Use CHIT
handoff safe mode with no cleartext for any secret transfer.

Sources: Path instructions, Linters/SAST tools

Comment on lines +29 to +134
# NATS Message Bus - Event-driven coordination backbone
NATS_URL=nats://nats:pmoves@nats:4222
NATS_USER=nats
NATS_PASSWORD=Mf3_GUNLQyHskfoDBkD_tFi9lxbVABzBdYbDfbdroyA
# NATS_BIND — host interface the published 4222/9223 ports bind to. Blank = compose
# default 0.0.0.0 (all interfaces). On a multi-homed/public VPS, set to the node's
# TAILNET IP so the bus is reachable over the mesh but NOT the public internet
# (nats:pmoves is a weak cred). Node-specific — set per node; never commit a real IP.
NATS_BIND=

# Meilisearch - Full-text search
MEILI_API_KEY=WoRF0KvKlJOA2GCROtesoJPZnLdcDaFvwfmCXpe5lCg

# Neo4j - Graph database
NEO4J_URL=bolt://neo4j:7687

# Supabase REST (internal docker URL — set by bootstrap)
SUPABASE_REST_URL=http://supabase-kong:8000/rest/v1
SUPABASE_BOOT_USER_REFRESH=

# Postgres service password
SERVICE_PASSWORD_POSTGRES=X70r1PCyBFFalzuAEXN8OO9aKrYElF55k6AKnjbQG1M

# Anthropic base URL (for proxied access)
ANTHROPIC_BASE_URL=https://api.anthropic.com

# API timeout (ms)
API_TIMEOUT_MS=3000000

# Agent Zero - Control-plane orchestrator
AGENT_ZERO_IMAGE=ghcr.io/powerfulmoves/pmoves-agent-zero:pmoves-latest

# Anthropic API
ANTHROPIC_API_KEY=dJUUJyJWn9-2Gkn-IkOoph57W7AA-HuArK2DbOAGF6k
ANTHROPIC_AUTH_TOKEN=yH7UxxuQFtQbrsj2VQY8tX9QsuvKjiqTxI6nAi2S51s

# Archon - Supabase-driven agent service
ARCHON_IMAGE=ghcr.io/powerfulmoves/pmoves-archon:pmoves-latest
# Leave empty to let runtime-specific SUPA_REST_URL/SUPABASE_URL wiring set Archon's base URL.
ARCHON_SUPABASE_BASE_URL=
ARCHON_UI_IMAGE=ghcr.io/powerfulmoves/pmoves-archon-ui:pmoves-latest

# TensorZero Gateway - Primary LLM provider & observability
TENSORZERO_BASE_URL=http://tensorzero-gateway:3000
TENSORZERO_HOST_URL=http://localhost:3030
TENSORZERO_MODEL=tensorzero::model_name::chat_default
TENSORZERO_TIMEOUT_SECONDS=60
TENSORZERO_EMBED_MODEL=qwen3_embedding_4b_local
TENSORZERO_EMBED_BATCH_SIZE=16
TENSORZERO_EMBED_TIMEOUT_SECS=120
# TensorZero ClickHouse - WARNING: Change credentials for production
TENSORZERO_CLICKHOUSE_URL=http://tensorzero-clickhouse:8123
TENSORZERO_CLICKHOUSE_GATEWAY_URL=http://tensorzero:tensorzero@tensorzero-clickhouse:8123/default
TENSORZERO_CLICKHOUSE_USER=clickhouse
TENSORZERO_CLICKHOUSE_PASSWORD=LOVLTAE2JHNKy3FVX5TSMSCgGpwVi_Yj0gtsTHY6MMI
TENSORZERO_CLICKHOUSE_DB=tensorzero

# Model sync/seeding controls
MODEL_SYNC_SOURCE=auto
OLLAMA_SEED_MODELS=

# ============================================================================
# SUPABASE CONFIGURATION (Standardized Naming)
# ============================================================================
# These align with PMOVES-supabase fork naming conventions
# See: pmoves/docs/SUPABASE_UNIFIED_SETUP.md

# Core JWT configuration
JWT_SECRET=anfwv4veQowpyeBNu+0RM9lj3cZwyEEeskBZ5+7GudwvnW8LJ2lm/tMr2SUqZmxt
JWT_EXPIRY=3600
JWT_ALGORITHM=HS256

# Runtime mode (production default = compose, CLI is backup/bootstrap)
SUPABASE_RUNTIME=compose

# Topology mode: docked (full compose), hybrid (compose+external), standalone, auto (detect)
# DOCKED_MODE is the legacy boolean — TOPOLOGY_MODE supersedes it.
TOPOLOGY_MODE=standalone
DOCKED_MODE=false

# Supabase JWT tokens (public keys - safe to commit)
# Standard demo tokens - replace with your own generated keys
ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlLWxvY2FsIiwiaWF0IjoxNjQxNzY5MjAwLCJleHAiOjE3OTk1MzU2MDB9.48Wyyv4HsidRQxDOwjBwbyYyya3BolhA8zdqg2VC3ys
SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UtbG9jYWwiLCJpYXQiOjE2NDE3NjkyMDAsImV4cCI6MTc5OTUzNTYwMH0.1-ubayYLPveeVu6Wyzgp7N4_bd0WzssPZXMm3Lt_Z58

# Supabase URLs
SITE_URL=http://localhost:3000
API_EXTERNAL_URL=http://localhost:8000

# Database credentials
SUPABASE_DB_USER=pmoves
SUPABASE_DB_PASSWORD=CsSrGrZuKLOdoEyHcYWeQiJMtAcFAK2d859WRjCkGKuUKliD
SUPABASE_DB_NAME=pmoves
SUPABASE_DB_HOST=supabase-db
SUPABASE_DB_PORT=5432

# Legacy variable names (for backward compatibility)
SUPABASE_JWT_SECRET=anfwv4veQowpyeBNu+0RM9lj3cZwyEEeskBZ5+7GudwvnW8LJ2lm/tMr2SUqZmxt
SUPABASE_JWT_EXP=${JWT_EXPIRY}
SUPABASE_JWT_ALGORITHM=${JWT_ALGORITHM}
SUPABASE_PUBLISHABLE_KEY=${ANON_KEY}
SUPABASE_SECRET_KEY=${SERVICE_ROLE_KEY}
SUPABASE_SITE_URL=http://localhost:3000
SUPABASE_PUBLIC_URL=http://localhost:8000
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlLWxvY2FsIiwiaWF0IjoxNjQxNzY5MjAwLCJleHAiOjE3OTk1MzU2MDB9.48Wyyv4HsidRQxDOwjBwbyYyya3BolhA8zdqg2VC3ys
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UtbG9jYWwiLCJpYXQiOjE2NDE3NjkyMDAsImV4cCI6MTc5OTUzNTYwMH0.1-ubayYLPveeVu6Wyzgp7N4_bd0WzssPZXMm3Lt_Z58

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

Do not commit live secrets in the pre-funnel env file.

This “example” file contains concrete DB passwords, JWT secrets, service-role tokens, provider API keys, MinIO/Neo4j/NATS credentials, CHIT passphrases, and other operational secrets. Replace with placeholders or generate via the CHIT/secrets funnel, then rotate every exposed value. As per path instructions, for this PR’s env.shared.pre-funnel and env-tier additions, use CHIT handoff safe mode with no cleartext.

Also applies to: 144-170, 178-241, 271-328, 347-409, 463-526, 611-656

🧰 Tools
🪛 Betterleaks (1.6.0)

[high] 111-111: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 112-112: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 133-133: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 134-134: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 32-32: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 40-40: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 62-62: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 63-63: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 83-83: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 97-97: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 120-120: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 126-126: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/env.shared.pre-funnel` around lines 29 - 134, The
env.shared.pre-funnel file currently commits live credentials and secrets, which
must be removed. Replace all concrete values in the shared pre-funnel env
template with placeholders or safe defaults, and route any real values through
the CHIT/secrets funnel in handoff-safe mode; keep the same keys but ensure no
cleartext secrets remain anywhere in this template or the related env-tier
additions. Use the existing variable groups in the file (for example NATS,
Meilisearch, Neo4j, Supabase, TensorZero, JWT, and service-role settings) to
locate and sanitize every exposed secret before committing.

Sources: Path instructions, Linters/SAST tools

Comment thread pmoves/env.tier-media
Comment on lines +26 to +33
MINIO_ACCESS_KEY=pm_minio_xzqnyuop
MINIO_BUCKET=pmoves-comfyui
MINIO_ENDPOINT=minio:9000
MINIO_OUTPUT_BUCKET=outputs
MINIO_SECRET_KEY=1Gp57R863NajfHd7FsvOQyPRobZZC7oDen7cAaxR058
MINIO_SECURE=false
NATS_URL=nats://nats:pmoves@nats:4222
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIiwiaXNzIjoic3VwYWJhc2UtbG9jYWwiLCJpYXQiOjE2NDE3NjkyMDAsImV4cCI6MTc5OTUzNTYwMH0.1-ubayYLPveeVu6Wyzgp7N4_bd0WzssPZXMm3Lt_Z58

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

Remove generated plaintext secrets from the committed env tier.

This auto-generated file now contains a MinIO secret and a Supabase service-role JWT. Update the secrets funnel/manifest source, regenerate locally, keep generated tier outputs out of review, and rotate the exposed credentials. Based on learnings, pmoves/env.tier-* files are auto-generated by pmoves.tools.secrets_sync and should not be directly edited; update the source-of-truth secrets flow instead.

🧰 Tools
🪛 Betterleaks (1.6.0)

[high] 33-33: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)


[high] 30-30: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/env.tier-media` around lines 26 - 33, Remove the committed plaintext
secrets from the generated env tier and restore this file to only
auto-generated, non-sensitive output. Update the source-of-truth secrets flow
used by pmoves.tools.secrets_sync (the secrets funnel/manifest), regenerate the
tier locally, and keep pmoves/env.tier-* out of direct edits; also rotate the
exposed MINIO_SECRET_KEY and SUPABASE_SERVICE_ROLE_KEY credentials.

Sources: Learnings, Linters/SAST tools

Comment thread pmoves/Makefile Outdated
Comment on lines +615 to +627
PGPASSWORD=$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}} docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -h localhost -U pmoves -d pmoves -c "CREATE TABLE IF NOT EXISTS public.pmoves_bootstrap_history (kind text NOT NULL, filename text NOT NULL, applied_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (kind, filename));"; \
if [ -d "supabase/migrations" ]; then \
for migration in $$(find supabase/migrations -maxdepth 1 -type f -name '*.sql' | LC_ALL=C sort); do \
[ -f "$$migration" ] || continue; \
name=$$(basename "$$migration"); \
applied=$$(docker exec -i "$$db" psql -U ${POSTGRES_USER:-pmoves} -d ${POSTGRES_DB:-pmoves} -tAc "SELECT 1 FROM public.pmoves_bootstrap_history WHERE kind='migration' AND filename='$$name' LIMIT 1;" | tr -d '[:space:]'); \
applied=$$(PGPASSWORD=$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}} docker exec -i "$$db" psql -h localhost -U pmoves -d pmoves -tAc "SELECT 1 FROM public.pmoves_bootstrap_history WHERE kind='migration' AND filename='$$name' LIMIT 1;" | tr -d '[:space:]'); \
if [ "$$applied" = "1" ]; then \
echo " Skipping migration (already applied): $$name"; \
continue; \
fi; \; echo " Applying migration: $$name"; \
docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -U ${POSTGRES_USER:-pmoves} -d ${POSTGRES_DB:-pmoves} < "$$migration"; \
docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -U ${POSTGRES_USER:-pmoves} -d ${POSTGRES_DB:-pmoves} -c "INSERT INTO public.pmoves_bootstrap_history(kind, filename) VALUES ('migration', '$$name') ON CONFLICT DO NOTHING;"; \
fi; \
echo " Applying migration: $$name"; \
PGPASSWORD=$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}} docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -h localhost -U pmoves -d pmoves < "$$migration"; \
PGPASSWORD=$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}} docker exec -i "$$db" psql -v ON_ERROR_STOP=1 -h localhost -U pmoves -d pmoves -c "INSERT INTO public.pmoves_bootstrap_history(kind, filename) VALUES ('migration', '$$name') ON CONFLICT DO NOTHING;"; \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Pass PGPASSWORD into the docker exec process.

PGPASSWORD=... docker exec ... psql sets the variable on the Docker client, not inside the DB container where psql runs. With -h localhost, these calls can fail with “no password supplied”; use docker exec -e PGPASSWORD=....

Suggested patch pattern
-PGPASSWORD=$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}} docker exec -i "$$db" psql ...
+docker exec -e PGPASSWORD="$${POSTGRES_PASSWORD:-$${SUPABASE_DB_PASSWORD:-}}" -i "$$db" psql ...

Also applies to: 636-643, 700-710

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/Makefile` around lines 615 - 627, The psql invocations in the
bootstrap migration flow are setting PGPASSWORD on the docker exec command
itself, so the variable never reaches the container where psql runs. Update the
affected commands in the bootstrap logic to pass PGPASSWORD into docker exec
with its environment flag, and apply the same fix consistently in the
migration/history steps referenced by the bootstrap loop and the other matching
psql calls in this Makefile. Use the existing bootstrap migration command block
and its helper flow as the target for the change.

Comment on lines +60 to +62
-- Grant permissions
GRANT SELECT ON pmoves_core.persona_enhancements TO anon, authenticated, service_role;
GRANT INSERT, UPDATE, DELETE ON pmoves_core.persona_enhancements TO authenticated, service_role;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Unrestricted write access for authenticated with no RLS.

persona_enhancements gets no ENABLE ROW LEVEL SECURITY anywhere in this file, yet any authenticated user is granted INSERT, UPDATE, DELETE. Since this table drives dynamic prompt/tool/weight overrides applied at agent-creation time (per the table comment and enhancement types), any authenticated user could inject arbitrary prompt/tool overrides into any persona (including Security/Archon), which is a direct configuration-tampering / prompt-injection vector.

🔒 Restrict writes to service_role and add RLS
-GRANT SELECT ON pmoves_core.persona_enhancements TO anon, authenticated, service_role;
-GRANT INSERT, UPDATE, DELETE ON pmoves_core.persona_enhancements TO authenticated, service_role;
+GRANT SELECT ON pmoves_core.persona_enhancements TO authenticated, service_role;
+GRANT INSERT, UPDATE, DELETE ON pmoves_core.persona_enhancements TO service_role;
+
+ALTER TABLE pmoves_core.persona_enhancements ENABLE ROW LEVEL SECURITY;
+CREATE POLICY persona_enhancements_service_only ON pmoves_core.persona_enhancements
+  USING (auth.role() = 'service_role')
+  WITH CHECK (auth.role() = 'service_role');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250103000000_persona_enhancements.sql` around
lines 60 - 62, The `persona_enhancements` migration currently grants write
access to `authenticated` without any row-level protection, which allows direct
tampering with persona override data. Update the migration to enable RLS on
`pmoves_core.persona_enhancements`, add appropriate policies, and restrict
INSERT/UPDATE/DELETE so only `service_role` can modify rows. Keep `GRANT SELECT`
for read access if needed, and ensure the RLS/policy setup is defined alongside
the existing table setup in this migration.

Comment on lines +12 to +19
-- Grant SELECT on existing tables for read paths (RLS still applies where enabled)
EXECUTE 'GRANT SELECT ON ALL TABLES IN SCHEMA pmoves_core TO anon, authenticated, service_role';
EXECUTE 'GRANT SELECT ON ALL TABLES IN SCHEMA pmoves_kb TO anon, authenticated, service_role';

-- Default privileges for future tables
EXECUTE 'ALTER DEFAULT PRIVILEGES IN SCHEMA pmoves_core GRANT SELECT ON TABLES TO anon, authenticated, service_role';
EXECUTE 'ALTER DEFAULT PRIVILEGES IN SCHEMA pmoves_kb GRANT SELECT ON TABLES TO anon, authenticated, service_role';
END $$;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

Blanket anon read access to all pmoves_core/pmoves_kb tables (current and future), with no RLS anywhere.

GRANT SELECT ON ALL TABLES IN SCHEMA pmoves_core/pmoves_kb TO anon, authenticated, service_role plus ALTER DEFAULT PRIVILEGES for all future tables makes every table in these schemas world-readable via PostgREST as soon as an anon key is used — since none of the tables created across this cohort (assets, documents/sections/chunks, grounding_packs, personas, persona_eval_gates, persona_enhancements, consciousness_theories, geometry_parameter_packs) enable Row Level Security. In particular, pmoves_core.personas.system_prompt_template/tools_access/behavior_weights/nats_subjects (seeded in 20250105000000_seed_standard_personas.sql) contain full internal system prompts and infra topology (ports, NATS subjects, service names) that would become publicly readable by anyone with the anon key — directly contradicting the "Zero Trust"/"least privilege" guidance embedded in the seeded Security persona's own prompt. persona_enhancements (writable by authenticated, see separate comment) would also be fully anon-readable.

Recommend either enabling RLS with default-deny policies on all sensitive tables before this grant is exercised, or scoping the grants to only the tables intended for public read (excluding personas, persona_enhancements, pack_members).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250104000000_pmoves_core_rest_grants.sql` around
lines 12 - 19, The current grant block makes every existing and future table in
pmoves_core and pmoves_kb readable by anon/authenticated/service_role, which
exposes sensitive data because RLS is not enabled on these tables. Update the
migration logic around the GRANT/ALTER DEFAULT PRIVILEGES statements to scope
access only to the intended public-read tables, or add default-deny RLS policies
before granting access. Use the existing symbols pmoves_core, pmoves_kb, and the
grant section in pmoves_core_rest_grants.sql to identify where to narrow or gate
the permissions, and exclude sensitive tables such as personas,
persona_enhancements, and pack_members from blanket SELECT privileges.

Comment on lines +206 to +214
CREATE POLICY "Admins can view all VPN nodes"
ON pmoves_core.vpn_nodes FOR SELECT
USING (
EXISTS (
SELECT 1 FROM pmoves_core.vpn_nodes vn
WHERE vn.user_id = auth.uid()
AND 'tag:admin' = ANY(vn.tags)
)
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the target migration and nearby RLS-related code.
git ls-files 'pmoves/supabase/migrations/*' | sed -n '1,120p'
echo '---'
ast-grep outline pmoves/supabase/migrations/20250108000000_remote_access.sql --view expanded || true
echo '---'
rg -n "CREATE POLICY|SECURITY DEFINER|auth\.uid\(\)|vpn_nodes|tag:admin|search_path" pmoves/supabase/migrations pmoves/supabase -S

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 49596


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the relevant section of the migration with line numbers.
sed -n '180,240p' pmoves/supabase/migrations/20250108000000_remote_access.sql | cat -n

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2392


Avoid self-recursive RLS for admin checks.

This vpn_nodes policy reads pmoves_core.vpn_nodes while RLS is being evaluated on the same table, which can trigger recursion errors and block the admin paths in remote_sessions and vpn_auth_keys that reuse the same check.

Move the admin lookup into a SECURITY DEFINER helper with a fixed search_path, then call that from the policies.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 206
- 214, The admin check in the vpn_nodes SELECT policy is self-recursive because
it queries pmoves_core.vpn_nodes during RLS evaluation. Move that lookup into a
SECURITY DEFINER helper with a fixed search_path, then update the vpn_nodes
policy and the related remote_sessions and vpn_auth_keys policies to call the
helper instead of querying the table directly.

Comment on lines +286 to +288
SELECT ARRAY_AGG(DISTINCT unnest(tags)) INTO v_user_tags
FROM pmoves_core.vpn_nodes
WHERE user_id = p_user_id AND is_online = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'File outline and surrounding lines:\n'
wc -l pmoves/supabase/migrations/20250108000000_remote_access.sql
sed -n '250,310p' pmoves/supabase/migrations/20250108000000_remote_access.sql

printf '\nSearch for similar aggregation patterns in repo:\n'
rg -n "ARRAY_AGG\\s*\\([^)]*unnest\\(" -S .

printf '\nPostgreSQL docs check (if web access is available):\n'
python3 - <<'PY'
print("No-op placeholder for local semantic probe if needed.")
PY

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2519


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'File outline and surrounding lines:\n'
wc -l pmoves/supabase/migrations/20250108000000_remote_access.sql
sed -n '250,310p' pmoves/supabase/migrations/20250108000000_remote_access.sql

printf '\nSearch for similar aggregation patterns in repo:\n'
rg -n "ARRAY_AGG\\s*\\([^)]*unnest\\(" -S .

Repository: POWERFULMOVES/PMOVES.AI

Length of output: 2412


🌐 Web query:

PostgreSQL aggregate function calls cannot contain set-returning function calls use a LATERAL query unnest aggregate arguments

💡 Result:

In PostgreSQL, aggregate functions cannot accept set-returning functions (SRFs) directly as arguments because it creates ambiguity regarding the expected number of rows and how the aggregation should be processed [1][2][3]. To resolve this error, you must move the set-returning function out of the aggregate argument list and into the FROM clause using a LATERAL JOIN [2][4]. This flattens the set into individual rows before the aggregation occurs [2][5]. Standard Workaround: Instead of calling: SELECT SUM(unnest(my_array_column)) FROM my_table; Use a LATERAL join: SELECT SUM(u.val) FROM my_table t CROSS JOIN LATERAL unnest(t.my_array_column) AS u(val); Explanation: 1. The LATERAL keyword allows the unnest function to reference columns from the preceding FROM items (in this case, t.my_array_column) [6]. 2. The CROSS JOIN LATERAL effectively flattens the array, creating a new row for each element [2][5]. 3. You can then perform standard aggregations (like SUM, COUNT, or AVG) on these flattened rows [2][5]. This approach is the standard, documented pattern for transforming sets generated by functions into a format compatible with aggregate functions [2][4].

Citations:


Move unnest() out of ARRAY_AGG. ARRAY_AGG(DISTINCT unnest(tags)) is invalid PostgreSQL syntax and will fail migration execution. Use CROSS JOIN LATERAL unnest(vn.tags) AS tag(tag) and aggregate DISTINCT tag instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250108000000_remote_access.sql` around lines 286
- 288, The query that builds v_user_tags is using invalid PostgreSQL syntax by
calling unnest() inside ARRAY_AGG. Update the migration SQL so the unnest
happens in the FROM clause via a lateral join against pmoves_core.vpn_nodes,
then aggregate DISTINCT on the unnested tag value instead of ARRAY_AGG(DISTINCT
unnest(tags)).

Comment on lines +158 to +203
-- Grant permissions to anon role for development
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_messages TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_sessions TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_personas TO anon;

-- RLS Policies for voice_messages
DO $$
BEGIN
CREATE POLICY voice_messages_anon_all
ON voice_messages
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;

-- RLS Policies for voice_sessions
DO $$
BEGIN
CREATE POLICY voice_sessions_anon_all
ON voice_sessions
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;

-- RLS Policies for voice_personas
DO $$
BEGIN
CREATE POLICY voice_personas_anon_all
ON voice_personas
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Do not grant full anon access to voice data.

These tables contain user identifiers, transcripts, audio URLs, AI responses, and persona prompts. anon can currently read, insert, update, and delete all rows because grants and RLS both allow everything. This should fail closed unless there is a user-scoped authenticated policy.

Safer default
--- Grant permissions to anon role for development
-GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_messages TO anon;
-GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_sessions TO anon;
-GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_personas TO anon;
-
--- RLS Policies for voice_messages
-DO $$
-BEGIN
-  CREATE POLICY voice_messages_anon_all
-    ON voice_messages
-    FOR ALL
-    TO anon
-    USING (true)
-    WITH CHECK (true);
-EXCEPTION
-  WHEN duplicate_object THEN NULL;
-END;
-$$;
+-- Keep voice data service-owned by default.
+REVOKE ALL ON TABLE voice_messages FROM anon;
+REVOKE ALL ON TABLE voice_sessions FROM anon;
+REVOKE ALL ON TABLE voice_personas FROM anon;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
-- Grant permissions to anon role for development
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_messages TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_sessions TO anon;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE voice_personas TO anon;
-- RLS Policies for voice_messages
DO $$
BEGIN
CREATE POLICY voice_messages_anon_all
ON voice_messages
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;
-- RLS Policies for voice_sessions
DO $$
BEGIN
CREATE POLICY voice_sessions_anon_all
ON voice_sessions
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;
-- RLS Policies for voice_personas
DO $$
BEGIN
CREATE POLICY voice_personas_anon_all
ON voice_personas
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;
-- Keep voice data service-owned by default.
REVOKE ALL ON TABLE voice_messages FROM anon;
REVOKE ALL ON TABLE voice_sessions FROM anon;
REVOKE ALL ON TABLE voice_personas FROM anon;
-- RLS Policies for voice_sessions
DO $$
BEGIN
CREATE POLICY voice_sessions_anon_all
ON voice_sessions
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;
-- RLS Policies for voice_personas
DO $$
BEGIN
CREATE POLICY voice_personas_anon_all
ON voice_personas
FOR ALL
TO anon
USING (true)
WITH CHECK (true);
EXCEPTION
WHEN duplicate_object THEN NULL;
END;
$$;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pmoves/supabase/migrations/20250110000000_voice_messages.sql` around lines
158 - 203, The anon access setup for voice data is too permissive because the
current grants and policies on voice_messages, voice_sessions, and
voice_personas allow unrestricted read/write/delete. Update the migration to
remove the full GRANTs to anon and replace the FOR ALL policies with a
fail-closed default that only allows access through authenticated, user-scoped
policies. Use the existing policy blocks named voice_messages_anon_all,
voice_sessions_anon_all, and voice_personas_anon_all to locate and narrow or
remove the unsafe behavior.

POWERFULMOVES pushed a commit that referenced this pull request Jul 2, 2026
- Add reviews/HOST_ACCESS_AND_BLOCKERS_HANDOFF_2026-06-26.md with merged PR records through #1924, #1925, #1926.
- Add CATACLYSM_STUDIOS_INC/PMOVES-5-Year-Financial-Model-2026-06.md (mid-year climate update).
- Mark CATACLYSM_STUDIOS_INC/PMOVES-5-Year-Financial-Model.md as superseded with pointer to the 2026-06 update.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant