dot-iu-cutter v0.4 — Connection Env Keys Command-Review Package r2 (FR-1 resolved; command-review only; not executed)
dot-iu-cutter v0.4 — Connection Env Keys Command-Review Package
document_path: knowledge/dev/laws/dieu44-trien-khai/v0.4-db-adapter-execution/dot-iu-cutter-v0.4-connection-env-keys-command-review-package-2026-05-17.md
revision: r2
date: 2026-05-17
author: Agent (Claude Code CLI, Opus 4.7 1M)
verifier: GPT (review pending — r2 routes the FR-1 resolution + revised command-review in)
phase: v0.4 — CONNECTION ENV KEYS COMMAND-REVIEW (command-review only)
opened_by: GPT command-review r1 review = substance PASS, execution NOT
authorized, FR-1 must be resolved before any .env write
+ explicit User "v0.4 connection env keys FR-1 resolution + r2" prompt.
status: command_review_only_pending_gpt_review — NOTHING EXECUTED
delta_from_r1: ONLY DOT_CUTTER_DB_SSLMODE require → disable (FR-1 resolved
via read-only prod SSL inspection §3a). Command sequence C-01..C-08,
safety gates G-1..G-8, rollback plan, non-scope = UNCHANGED from r1.
⛔ COMMAND-REVIEW ONLY. NOT executed. No
.envedit, no secret value read/printed, no runtime connection, no code change, no dry-run, no CUT/VERIFY, no deploy, no service restart, no role/GRANT change, no secret rotation. Read-only docker topology + read-only PostgreSQL SSL inspection were performed (authorized); they changed nothing.
§1 — Objective
Add exactly four non-secret, shared connection component keys to the
approved substrate /opt/incomex/docker/.env so a FUTURE authorized code
cycle can build a connection without hardcoding host/port/db/sslmode and
without any DSN-with-password (per design docs 2/3 + GPT DA-1):
DOT_CUTTER_DB_HOST DOT_CUTTER_DB_PORT DOT_CUTTER_DB_NAME DOT_CUTTER_DB_SSLMODE
No password material is added, read, or touched. The 4 LIVE credential keys are NOT modified.
§2 — Current .env Key Inventory (read-only; NO values printed)
Verified by read-only inspection on VPS 38.242.240.89 (key NAMES only, via
grep -oE '^DOT_CUTTER[A-Za-z0-9_]*=' … | tr -d '=' — values never read):
env_file: /opt/incomex/docker/.env
permissions: 600 root:root (CONFIRMED — satisfies gate G-1)
credential_keys_present (names only, values NEVER read/printed):
- DOT_CUTTER_EXEC_DB_USER PRESENT
- DOT_CUTTER_EXEC_DB_PASSWORD PRESENT
- DOT_CUTTER_VERIFY_DB_USER PRESENT
- DOT_CUTTER_VERIFY_DB_PASSWORD PRESENT
→ exactly the 4 GPT-accepted live credential keys (credential-execution
report §6 / GPT credential review §4). Satisfies gate G-2.
target_connection_keys (the 4 to be added):
grep -cE '^DOT_CUTTER_DB_(HOST|PORT|NAME|SSLMODE)=' = 0 → ALL ABSENT
→ no pre-existing / duplicate / conflicting DOT_CUTTER_DB_* keys.
Satisfies gate G-4.
§3 — Host Discovery (read-only topology; NOT guessed)
Evidence from docker ps, docker network ls, docker inspect postgres,
and read-only docker-compose.yml service/network grep:
compose_dir: /opt/incomex/docker (docker-compose.yml; .env is its substrate)
compose_network: docker_incomex (bridge, local) — the single app network
postgres_container:
container_name: postgres
image: postgres:16
network: docker_incomex
network_aliases: [postgres] (docker DNSNames: "postgres")
ip: 172.18.0.2 (DHCP — NOT stable, MUST NOT be used as the value)
host_port_publish: 127.0.0.1:5432:5432 (loopback only)
compose_internal_port: 5432
established_convention (other services on docker_incomex reaching PG):
incomex-directus : DB_HOST: postgres DB_PORT: '5432'
incomex-agent-data: DIRECTUS_DB_HOST: postgres / PG_HOST: postgres
DB/PG_PORT: '5432'
cutter_agent_service_in_compose: NONE (no cutter/iu-cutter/dot-agent service
defined yet — runtime binding is a later gated cycle, DA-6)
Recommended host rationale (non-guess): every existing service that
talks to PostgreSQL on this stack resolves it by the docker-network DNS
name postgres on port 5432 (verified container alias + DNSName +
two sibling services' config). The cutter-agent's only coherent runtime
context — given its credentials already live in this compose stack's
.env — is a service on docker_incomex, where postgres/5432 is the
proven, topology-derived endpoint. The container IP (172.18.0.2) is
explicitly rejected (DHCP, unstable). The loopback publish
(127.0.0.1:5432) is rejected as the value because it only works for a
host-process context, which contradicts the compose-substrate placement and
the design's no-localhost-fallback rule; if a host-process runtime is later
chosen, that is a deviation to be raised at the runtime-binding
command-review (DA-6), not assumed here.
§3a — FR-1 Resolution: Production PostgreSQL SSL Status (read-only)
GPT required FR-1 (sslmode value) be resolved before any .env write,
because DOT_CUTTER_DB_SSLMODE directly determines whether the future
RealPostgresAdapter can connect at all. Resolved here by read-only
inspection of the production postgres container — no connect, no auth, no
secret, nothing changed.
Evidence (VPS 38.242.240.89, container postgres, image postgres:16,
network docker_incomex — the same PG these env keys target):
-
docker ps→ production PG container is namedpostgres(imagepostgres:16). (Siblingpg-dry-run-*containers are unrelated ephemeral dry-run envs; not inspected for this decision.) -
Server SSL settings via read-only
pg_settingsquery as the container's owndirectusrole (POSTGRES_USER=directus; nopostgressuperuser role exists; no password printed):ssl | off ssl_ca_file | (empty) ssl_cert_file | server.crt ← default config NAME only ssl_key_file | server.key ← default config NAME only ssl_library | OpenSSL ← compiled-in, but NOT enabled -
Cert/key file presence in the data dir:
ls /var/lib/postgresql/data/server.crt → No such file or directory ls /var/lib/postgresql/data/server.key → No such file or directoryThe
ssl_cert_file/ssl_key_filesettings are merely PostgreSQL's built-in default names; the actual files do not exist. Even ifsslwere flipped on, the server has no certificate/key to present.
Determination:
ssl_enabled: NO (pg_settings ssl = off)
cert_key_present: NO (server.crt / server.key absent from data dir)
ssl_library_compiled: yes (OpenSSL — capability exists, NOT configured)
intra_docker_sslmode_require_usable: NO
rationale: with server ssl=off, a libpq/psycopg client connecting with
sslmode=require is REJECTED (require = SSL-only, no fallback). Sibling
services (incomex-directus, incomex-agent-data) already connect to this
PG over the docker_incomex private bridge WITHOUT TLS — confirming the
established, working transport for this stack is plaintext on the
internal bridge.
FR-1 decision: SSL is off and not usable on production PG. Per the
resolution rule, DOT_CUTTER_DB_SSLMODE is changed from require →
disable for the v0.4 internal docker-bridge runtime. This matches the
proven sibling-service transport (private bridge, no TLS) and ensures the
future RealPostgresAdapter can actually connect.
Forward hardening note (NOT a v0.4 blocker): server-side TLS
(generate/mount server.crt+server.key, set ssl=on) followed by
client sslmode=verify-full + CA pinning remains a future hardening track,
out of scope for v0.4. It would be its own gated design+command-review
cycle and would re-revise this key at that time. FR-1 is CLOSED for
v0.4 by selecting disable.
§4 — Exact Proposed .env Additions (NO password values)
Appended verbatim to /opt/incomex/docker/.env (one trailing block):
| Key | Proposed value | Source / authority |
|---|---|---|
DOT_CUTTER_DB_HOST |
postgres |
discovered topology §3 (docker DNS alias; matches directus/agent-data) |
DOT_CUTTER_DB_PORT |
5432 |
compose internal port; sibling-service convention; pending C-04 preflight |
DOT_CUTTER_DB_NAME |
directus |
GPT DA-1/§8 (cutter_governance schema lives in db directus) |
DOT_CUTTER_DB_SSLMODE |
disable |
FR-1 resolved §3a — prod PG ssl=off, no cert/key; require unusable; matches sibling no-TLS bridge transport (supersedes r1 require/DA-2; verify-full = future hardening) |
# --- dot-iu-cutter v0.4 connection components (non-secret; added 2026-05-17) ---
DOT_CUTTER_DB_HOST=postgres
DOT_CUTTER_DB_PORT=5432
DOT_CUTTER_DB_NAME=directus
DOT_CUTTER_DB_SSLMODE=disable
All four are non-secret. No DOT_CUTTER_DB_DSN is added (design forbids
DSN-with-password). No credential key is read, rewritten, or reordered.
FR-1 status: RESOLVED & CLOSED for v0.4 (see §3a). The r1 forward-risk
is no longer open; sslmode=disable is consistent with the verified
server state and the working sibling-service transport. Future server TLS
verify-fullis tracked as a separate future-hardening cycle, not a v0.4 connection-time risk.
§5 — Proposed Command Sequence (REVIEW TARGET — NOT executed)
UNCHANGED from r1. Only the §4
DOT_CUTTER_DB_SSLMODEvalue differs (require→disable); C-06 still appends the §4 block verbatim and C-07 still asserts the §4 values — which now carrydisable.
command_count: 8 (C-01..C-07 forward + C-08 conditional rollback)
C-01 preflight perms : stat -c '%a %U:%G' /opt/incomex/docker/.env
== "600 root:root" else ABORT (gate G-1). [read-only]
C-02 preflight creds : assert the 4 credential key NAMES present
(grep -c by name; values NEVER read). any missing → ABORT (G-2).
C-03 preflight absent: grep -cE '^DOT_CUTTER_DB_(HOST|PORT|NAME|SSLMODE)='
== 0 else ABORT (G-4 duplicate/conflict).
C-04 preflight host : from the INTENDED runtime context (ephemeral
throwaway container on docker_incomex, e.g.
`docker run --rm --network docker_incomex busybox \
nslookup postgres`) confirm `postgres` resolves AND port 5432 is
the intended endpoint; cannot resolve → ABORT (G-3). Read-only DNS
probe ONLY — does NOT connect to PostgreSQL, no auth, no .env read.
C-05 backup : cp -p /opt/incomex/docker/.env \
/opt/incomex/docker/.env.bak.<UTCSTAMP> ; record sha256 of both
(pre-change integrity anchor). perms preserved 600 root:root.
C-06 apply : append EXACTLY the 4-line block from §4 (idempotent —
guarded by C-03; no in-place rewrite of any existing line; no
secret echoed; no `set -x`).
C-07 verify : assert exactly the 4 new keys present with the §4
values (incl. DOT_CUTTER_DB_SSLMODE=disable); assert the credential
key NAME set == pre-set ∪ {4 new} (no credential key added/removed/
renamed); assert NO password value appears in any log/console
(grep guard, names-only); perms still 600 root:root; .env line
count == pre + 5 (4 keys + 1 comment). any check fails → C-08.
C-08 rollback (cond.) : ON C-07 failure or integrity mismatch — restore
/opt/incomex/docker/.env from the C-05 backup (full restore) OR, if
backup intact and only the appended block is the delta, remove ONLY
the 4 newly added non-secret keys + their comment line. Re-assert
perms 600 root:root and credential-name-set unchanged. Never edits
credential lines.
§6 — Safety Gates (abort conditions)
UNCHANGED from r1.
G-1 .env permissions ≠ 600 root:root → ABORT (C-01)
G-2 any of the 4 credential keys missing → ABORT (C-02)
G-3 proposed host cannot resolve from intended runtime ctx → ABORT (C-04)
G-4 any pre-existing/duplicate/conflicting DOT_CUTTER_DB_* → ABORT (C-03)
G-5 any secret value would be printed/logged/echoed → ABORT (all C;
commands use name-only greps, no `set -x`, no value interpolation)
G-6 post-apply credential-key NAME set changed → ROLLBACK (C-08)
G-7 post-apply perms drifted from 600 root:root → ROLLBACK (C-08)
G-8 backup sha mismatch on restore → ROLLBACK to
C-05 backup; if backup itself corrupt → STOP + NEEDS_HUMAN
§7 — Rollback Plan
UNCHANGED from r1.
pre_change_anchor: C-05 timestamped backup of .env (perms-preserving cp -p,
600 root:root) + sha256 of pre and post.
trigger: C-07 verify failure | G-6 | G-7 | integrity/sha mismatch.
action_primary: full restore of /opt/incomex/docker/.env from the C-05
backup (byte-identical → credential keys exactly as before).
action_minimal: if backup verified intact and the ONLY delta is the §4
appended block, remove just the 4 added non-secret keys + the comment
line; re-verify credential-name-set + perms.
never: edit/rewrite/reorder any credential line; print any secret value;
delete the backup until GPT confirms closeout.
post_rollback_state: .env == pre-change (4 connection keys absent again);
no credential change; perms 600 root:root.
§8 — Non-Scope (explicitly excluded from this cycle)
- no role / GRANT / privilege change
- no secret rotation, no password read/print/derive
- no code change (commit 689e53e untouched; ProductionDBAdapter still refuses)
- no runtime DB connection; no adapter binding
- no service restart; no compose up/recreate; no deploy
- no dry-run (in-memory or PG-backed)
- no CUT / VERIFY
- no server-side TLS enablement / cert generation (future hardening track)
- adding a service to docker-compose / choosing final runtime container =
deferred to runtime-binding command-review (DA-6) — NOT here
§9 — Output Summary
command_count: 8 (C-01..C-07 forward + C-08 conditional rollback)
proposed_keys:
DOT_CUTTER_DB_HOST=postgres
DOT_CUTTER_DB_PORT=5432
DOT_CUTTER_DB_NAME=directus
DOT_CUTTER_DB_SSLMODE=disable # r2: FR-1 resolved (was require in r1)
fr_1_resolution:
prod_pg_ssl: off (pg_settings ssl=off; ssl_ca_file empty)
cert_key_files: ABSENT (server.crt / server.key not in data dir)
ssl_library: OpenSSL compiled-in but NOT configured
sslmode_require_usable: NO (server ssl=off rejects require; no fallback)
decision: DOT_CUTTER_DB_SSLMODE=disable for v0.4 internal docker bridge
matches: sibling incomex-directus / incomex-agent-data no-TLS bridge transport
future_hardening: server TLS + client verify-full = separate gated cycle
fr_1_status: RESOLVED & CLOSED for v0.4
discovered_host_rationale: docker-network DNS alias `postgres` on
docker_incomex — verified container alias/DNSName + the convention used by
incomex-directus and incomex-agent-data; container IP & loopback publish
explicitly rejected; not guessed.
safety_gates: G-1..G-8 (perms / creds-present / host-resolves /
no-duplicate / no-secret-print / creds-unchanged / perms-stable /
backup-integrity) [UNCHANGED from r1]
rollback_plan: C-05 timestamped perms-preserving backup → full restore or
minimal 4-key removal; credential lines never touched [UNCHANGED from r1]
delta_from_r1: ONLY DOT_CUTTER_DB_SSLMODE require → disable + FR-1 closed;
command sequence / gates / rollback / non-scope unchanged
execution_status: BLOCKED — NOTHING EXECUTED; .env UNCHANGED; no secret
read; read-only topology + read-only PG SSL inspection only
ready_for_gpt_review: YES
agent_self_advance: PROHIBITED
End of v0.4 connection env keys command-review package r2 (FR-1 resolved → sslmode=disable; command-review only; not executed; .env unchanged; no secret read; next = GPT review of r2).