D28 — Deploy Build Verify Pack — Agent Prompt (Tier 1: Build Verify Only)
D28 — Deploy Build Verify Pack — Agent Prompt
Date: 2026-05-10 | Rev: 2 | GPT 11 patches: log safety, source cleanup, Docker boundaries, PM detection, no auto-rollback Agent: claude-go (VPS SSH + git on host) | Scope: Build verify only — KHÔNG DEPLOY Tier: build_verify_only (không phải build_plus_deploy hay live_smoke) Predecessor: D28 Phase 1B PARTIAL (commits 0947613 + d2db418)
Hard boundaries
NO_DEPLOY=true
NO_LIVE_ROUTE_SMOKE=true
NO_LIVE_HTTP_CALL_TO_PROD=true
NO_CURL_PRODUCTION_ROUTES=true
NO_CONTAINER_RESTART=true
NO_RUNNING_SERVICE_INTERRUPTION=true
NO_DIRECTUS_MUTATION=true
NO_PG_MUTATION=true
NO_PUBLISH_EVENT_OUTBOX=true
NO_CHANGE_TABLE_REGISTRY=true
NO_FIX_TBL_MODULES_LIST=true
NO_ADD_ENTITY_TYPE_COLUMN=true
NO_PACKAGE_INSTALL_ON_HOST=true
NO_LOCKFILE_CHANGE=true
NO_DOCKER_COMPOSE_UP=true
NO_DOCKER_COMPOSE_RESTART_RUNNING=true
NO_DOCKER_COMPOSE_DOWN=true
NO_DOCKER_COMPOSE_STOP_START=true
NO_DOCKER_COMPOSE_PUSH=true
NO_AUTO_ROLLBACK_ON_BUILD_FAIL=true
NO_FILE_MUTATION_OUTSIDE_TEMP=true
NO_PRINT_LOG_BEFORE_SECRET_SCAN=true
NO_SECRET_IN_CODE_OR_LOG=true
NO_PRINT_ENV_TOKEN_URL=true
NO_GUESS_SERVICE_NAME=true
Allowed Docker operations
ALLOWED:
docker compose run --rm <service> <command> # ephemeral, doesn't touch running
docker compose ps # read-only
docker compose config # read-only
docker inspect # read-only
docker images # read-only
docker logs # read-only
FORBIDDEN:
docker compose up [-d]
docker compose restart
docker compose down
docker compose stop / start
docker compose push
docker run (without --rm)
docker exec on running production service (write operations)
Mục tiêu (build_verify_only tier)
- Verify generated map artifact (commit 0947613) hoạt động đúng khi build
- Verify 3 consumer file changes (commit d2db418) typecheck pass
- Verify server import alias (
~/generated/...từserver/api/) hoạt động - Document deploy mechanism (KHÔNG execute) cho follow-up pack
- Document route smoke mechanism (KHÔNG execute) cho follow-up pack
KHÔNG thuộc scope pack này:
- Deploy
- Container restart
- Live route smoke
- Publish tbl_event_outbox
- Resume P3D notification
- Fix tbl_modules_list data
Phase 0 — Infrastructure inventory (READ-ONLY)
Apply lessons learned: verify environment TRƯỚC khi chạy bất kỳ command nào động đến build.
0A. Build mechanism discovery
ssh contabo "cd /opt/incomex/docker && cat docker-compose.yml | grep -A2 -E 'image|build:' | head -30"
ssh contabo "cd /opt/incomex/docker && cat nuxt-repo/docker-compose.local.yml 2>/dev/null | head -60 || echo NO_DEV_COMPOSE"
ssh contabo "cd /opt/incomex/docker/nuxt-repo && ls web/Dockerfile* 2>/dev/null"
ssh contabo "cd /opt/incomex/docker/nuxt-repo && cat web/Dockerfile | grep -E 'FROM|RUN|COPY|WORKDIR' | head -40"
ssh contabo "cd /opt/incomex/docker/nuxt-repo && cat web/package.json | grep -A20 '\"scripts\"'"
Identify:
- Production image build path (Dockerfile multi-stage)
- Dev compose presence (docker-compose.local.yml)
- Build commands (npm run build, pnpm build, etc.)
- Target output (.output directory)
0B. Available build paths analysis (PRIORITY ORDER)
Sau 0A, classify available build mechanisms theo thứ tự ưu tiên:
| Priority | Path | Mechanism | Available? | Allowed? |
|---|---|---|---|---|
| 1 | B1 | docker compose run --rm <dev-svc> (ephemeral) |
? | ✅ if dev compose exists |
| 2 | B3 | docker run --rm <existing-dev-image> |
? | ✅ if image exists |
| 3 | B4 | CI / GitHub Actions | ? | ✅ documentation only |
| 4 | B2 | docker compose build <prod-svc> |
? | ⚠️ requires explicit justification |
| N/A | B5 | Host pnpm/npm install + build | ❌ | violates NO_PACKAGE_INSTALL |
| N/A | B6 | Build in running prod container | ❌ | no source/deps + interrupts service |
Recommend path 1 nếu khả thi. B2 chỉ dùng nếu B1/B3/B4 đều không available, và phải document justification rõ.
Report: chosen_build_path=B1|B2|B3|B4|BLOCKED, chosen_path_justification=....
0C. Service name discovery (KHÔNG đoán)
Nếu B1 chosen, agent PHẢI discover dev service name từ docker-compose.local.yml:
ssh contabo "cd /opt/incomex/docker/nuxt-repo && docker compose -f docker-compose.local.yml config --services 2>/dev/null"
Nếu output rỗng hoặc nhiều services → STOP DEV_SERVICE_UNKNOWN. KHÔNG đoán tên service.
0D. Package manager detection
ssh contabo "cd /opt/incomex/docker/nuxt-repo/web && \
test -f pnpm-lock.yaml && echo PM=pnpm || \
(test -f package-lock.json && echo PM=npm || \
(test -f yarn.lock && echo PM=yarn || echo PM=UNKNOWN))"
Nếu PM=UNKNOWN → STOP PACKAGE_MANAGER_UNKNOWN. Tất cả command sau dùng đúng PM (pnpm build vs npm run build vs yarn build).
0E. Typecheck availability detection
ssh contabo "cd /opt/incomex/docker/nuxt-repo/web && grep -E '\"typecheck\"|\"type-check\"' package.json"
Nếu KHÔNG có script → typecheck_status=NOT_AVAILABLE (không FAIL).
0F. Existing image inventory
ssh contabo "docker images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}' | head -20"
Identify production image, dev image (nếu có), builder image (nếu retained).
0G. Deploy mechanism discovery (DOCUMENT ONLY)
ssh contabo "ls /opt/incomex/docker/*.yml"
ssh contabo "find /opt/incomex/docker -name 'deploy*' -o -name 'restart*' 2>/dev/null | head -10"
ssh contabo "cat /opt/incomex/docker/.github/workflows/*.yml 2>/dev/null | head -40 || cat /opt/incomex/docker/nuxt-repo/.github/workflows/*.yml 2>/dev/null | head -40"
Document deploy flow. KHÔNG execute.
0H. Smoke mechanism discovery (DOCUMENT ONLY)
ssh contabo "find /opt/incomex/docker/nuxt-repo -name 'smoke*' -o -name 'route-test*' 2>/dev/null | head -10"
0I. Auto-snapshot mechanism
ssh contabo "crontab -l 2>/dev/null | grep -i snapshot | head -5"
ssh contabo "find / -name '*snapshot*' 2>/dev/null | grep -v /proc | head -5"
Document mechanism. Account cho commit splits.
0J. Pre-build source tree state
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git status --porcelain > /tmp/d28-pre-state.txt && wc -l /tmp/d28-pre-state.txt"
Verify clean = empty. Save state cho post-build comparison.
Phase A — Build verify (no deploy, log-safety first)
Sau Phase 0 đã identify build path khả thi:
A.1. Pre-build state snapshot
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git log --oneline -3"
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git status --porcelain > /tmp/d28-pre.txt && wc -l /tmp/d28-pre.txt"
Verify HEAD includes both Phase 1B commits. Pre-state empty.
A.2. Log-safety pattern (rev2 critical)
Mọi build/typecheck command PHẢI follow pattern:
# 1. Generate unique temp log filename
TS=$(date +%s)
LOGFILE="/tmp/d28-build-verify-$TS.log"
# 2. Run command, redirect to log file (NOT stdout)
ssh contabo "<command> > $LOGFILE 2>&1; echo EXIT=\$?"
# 3. chmod 600 immediately
ssh contabo "chmod 600 $LOGFILE 2>/dev/null"
# 4. Scan secret BEFORE printing anything
ssh contabo "grep -qi 'token\\|secret\\|bearer\\|password\\|authorization' $LOGFILE && echo SECRET_SCAN=FAIL || echo SECRET_SCAN=PASS"
# 5. Only if SECRET_SCAN=PASS: print safe tail (excluding sensitive patterns)
ssh contabo "grep -v -i -E 'token|secret|bearer|password|authorization' $LOGFILE | tail -20"
# 6. Cleanup
ssh contabo "rm -f $LOGFILE"
CẤM: print 2>&1 | tail -N trực tiếp. Phải qua temp file + scan first.
A.3. Typecheck (chosen path, log-safe)
Tùy theo Phase 0B chosen path. Ví dụ B1 với detected PM:
# B1 + pnpm example:
TS=$(date +%s)
LOGFILE="/tmp/d28-typecheck-$TS.log"
ssh contabo "cd /opt/incomex/docker/nuxt-repo && \
docker compose -f docker-compose.local.yml run --rm <DEV_SERVICE> sh -c 'cd /app && pnpm typecheck' > $LOGFILE 2>&1; \
echo EXIT=\$?"
ssh contabo "chmod 600 $LOGFILE 2>/dev/null && \
grep -qi 'token\\|secret\\|bearer\\|password\\|authorization' $LOGFILE && \
echo TYPECHECK_LOG_SECRET_SCAN=FAIL || echo TYPECHECK_LOG_SECRET_SCAN=PASS"
# Print safe tail only if PASS
ssh contabo "grep -v -i -E 'token|secret|bearer|password|authorization' $LOGFILE | tail -20"
ssh contabo "rm -f $LOGFILE"
Nếu typecheck NOT_AVAILABLE (per 0E) → skip, report typecheck_status=NOT_AVAILABLE.
A.4. Build verify (log-safe)
Same pattern as A.3, replace command với pnpm build / npm run build / yarn build based on detected PM.
A.5. Import resolution verify
Build/typecheck PASS → all imports resolve correctly. KHÔNG cần additional grep verification (typecheck đã verify).
Nếu typecheck FAIL → check error message (already redacted in safe tail) cho import error patterns.
A.6. Source tree mutation check (post-build)
# Compare git status before/after
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git status --porcelain > /tmp/d28-post.txt && diff /tmp/d28-pre.txt /tmp/d28-post.txt"
Expected: No diff (build artifacts go to ephemeral container, not host source tree).
Nếu có diff:
.nuxt/directory → KNOWN_BUILD_ARTIFACT (Nuxt cache, safe to ignore).output/directory → KNOWN_BUILD_ARTIFACTnode_modules/directory → STOPUNEXPECTED_HOST_NODE_MODULES(means deps installed on host — vi phạm)- Anything else → STOP
UNEXPECTED_SOURCE_MUTATION
Cleanup chỉ KNOWN safe artifacts:
ssh contabo "cd /opt/incomex/docker/nuxt-repo/web && \
test -d .nuxt && rm -rf .nuxt && echo CLEANED_NUXT_CACHE; \
test -d .output && rm -rf .output && echo CLEANED_OUTPUT_CACHE"
KHÔNG cleanup unexpected files. Report all source tree changes.
# Verify post-cleanup clean
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git status --porcelain"
# Expected: empty
A.7. Temp log cleanup
ssh contabo "rm -f /tmp/d28-*.txt /tmp/d28-*.log 2>/dev/null; ls /tmp/d28-* 2>/dev/null || echo TEMP_FILES_CLEANED"
Report: logs_cleaned=true|false, temp_files_remaining=0|<list>.
A.8. Build fail → report only, NO auto rollback
Nếu build/typecheck FAIL:
- Capture safe error tail (already redacted in A.3/A.4)
- Document failure mode
- Recommend rollback in report
- KHÔNG auto-execute
git revert— rollback là quyết định governance, do User/GPT decide rollback_executed=falserollback_recommended=true
Cleanup temp/build artifacts (A.6/A.7) vẫn chạy regardless of build pass/fail.
Phase B — Deploy plan documentation (DON'T EXECUTE)
Document deploy steps cho follow-up pack:
deploy_mechanism=<from 0D>
deploy_steps_required=
1. ...
2. ...
deploy_user_facing_impact=container_restart_required|hot_reload|none
deploy_rollback_plan=git revert + re-deploy
deploy_estimated_duration=
deploy_traffic_implications=
KHÔNG execute deploy.
Phase C — Smoke plan documentation (DON'T EXECUTE)
Document smoke targets cho follow-up pack:
Routes to smoke (post-deploy, NOT in this pack)
13 registry entity routes:
/knowledge/registries/catalog
/knowledge/registries/table
/knowledge/registries/module
/knowledge/registries/dot_tool
/knowledge/registries/page
/knowledge/registries/collection
/knowledge/registries/agent
/knowledge/registries/checkpoint_type
/knowledge/registries/checkpoint_set
/knowledge/registries/entity_dependency
/knowledge/registries/checkpoint_instance
/knowledge/registries/changelog
/knowledge/registries/system_issue
3 non-registry pages affected by collectionMap:
/knowledge/workflows
/knowledge/modules
/knowledge/current-tasks
Special routes:
/admin/proposals
/knowledge/registries (index)
/knowledge/workflows/[id]?tab=matrix
/knowledge/workflows/[id]?tab=wcr
API endpoint:
/api/discovery/relations
Tổng: ~21 routes/endpoints. KHÔNG smoke trong pack này. KHÔNG smoke /knowledge/registries/event_outbox (route mới — chỉ verify sau khi publish ở Phase 1C).
Phase D — Report
Path: knowledge/dev/laws/dieu28-trien-khai/reports/d28-deploy-build-verify-pack-report.md
# D28 — Deploy Build Verify Pack Report
## Tier
tier=build_verify_only
deploy_performed=false
live_smoke_performed=false
## Phase 0 — Infrastructure inventory (READ-ONLY)
package_manager_detected=pnpm|npm|yarn|UNKNOWN
typecheck_script_present=true|false
dev_compose_service_name=
build_paths_available=[B1/B2/B3/B4 list]
recommended_build_path=
chosen_path_justification=
dev_compose_present=true|false
dev_image_available=true|false
deploy_mechanism=
smoke_mechanism_existing=true|false
auto_snapshot_documented=
pre_build_state_clean=true|false
## Phase A — Build verify
chosen_build_path=
typecheck_status=PASS|FAIL|BLOCKED|NOT_AVAILABLE
typecheck_exit_code=
typecheck_log_secret_scan=PASS|FAIL
build_status=PASS|FAIL|BLOCKED|NOT_AVAILABLE
build_exit_code=
build_log_secret_scan=PASS|FAIL
secret_scan_printed_matches=false
log_safety_pattern_followed=true
server_import_verify=PASS|FAIL|BLOCKED (via build/typecheck)
client_import_verify=PASS|FAIL|BLOCKED
ssr_import_verify=PASS|FAIL|BLOCKED
source_tree_mutation_check=PASS|FAIL
known_build_artifacts_cleaned=[.nuxt, .output, ...]
unexpected_files_detected=[list, empty if PASS]
post_cleanup_clean=true|false
logs_cleaned=true
temp_files_remaining=0|<list>
## Phase B — Deploy plan (NOT EXECUTED)
deploy_steps_documented=
deploy_user_facing_impact=
deploy_rollback_plan=git revert d2db418 0947613 + re-deploy
## Phase C — Smoke plan (NOT EXECUTED)
routes_to_smoke_count=21
relations_endpoint_to_smoke=true
event_outbox_route_smoke=DEFERRED_TO_PHASE_1C
## Attestation
no_deploy=true
no_live_route_smoke=true
no_live_http_call_to_prod=true
no_curl_production_routes=true
no_container_restart=true
no_running_service_interruption=true
no_directus_mutation=true
no_pg_mutation=true
no_publish_event_outbox=true
no_table_registry_mutation=true
no_secret_printed=true
no_log_printed_before_secret_scan=true
no_package_install_on_host=true
no_lockfile_change=true
no_docker_compose_up=true
no_docker_compose_restart_running=true
no_docker_compose_down=true
no_auto_rollback_executed=true
no_unexpected_source_mutation=true
## Status
phase_status=PASS|PARTIAL|FAIL|BLOCKED
build_verify_status=PASS|FAIL|BLOCKED|NOT_AVAILABLE
typecheck_status=PASS|FAIL|BLOCKED|NOT_AVAILABLE
rollback_executed=false
rollback_recommended=true|false
next_required_pack=
- D28_DEPLOY_AND_LIVE_SMOKE_PROMPT_REVIEW (if PASS — review + approval, không deploy thẳng)
- D28_BUILD_TOOLING_FIX (if PARTIAL)
- D28_GENERATED_MAP_FIX (if FAIL with import errors — User decides rollback)
- D28_BUILD_INFRASTRUCTURE_PACK (if BLOCKED)
rollback_commits=d2db418,0947613
rollback_command_for_user=ssh contabo "cd /opt/incomex/docker/nuxt-repo && git revert d2db418 0947613 --no-edit"
Rollback (governance decision, NOT auto)
Nếu build verify reveal broken state, rollback là quyết định User/GPT, không auto:
# User/GPT approves → execute manually:
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git revert d2db418 0947613 --no-edit"
Rollback verify:
ssh contabo "cd /opt/incomex/docker/nuxt-repo && git log --oneline -3"
Sau rollback, hardcoded maps được restore. Production container không bị ảnh hưởng (chưa redeploy).
Pack rev2: rollback_executed=false (always). Pack chỉ recommend, không execute revert.
Decision matrix sau pack
| Phase A result | Next pack |
|---|---|
| PASS | D28_DEPLOY_AND_LIVE_SMOKE_PROMPT_REVIEW (review + approval, không deploy thẳng) |
| PARTIAL (typecheck PASS, build BLOCKED) | D28_BUILD_TOOLING_FIX |
| FAIL (import error) | D28_GENERATED_MAP_FIX (User quyết định rollback) |
| BLOCKED (no build path available) | D28_BUILD_INFRASTRUCTURE_PACK |
D28 Deploy Build Verify Pack | Rev2 | Tier 1: build_verify_only | NO DEPLOY | 2026-05-10