KB-6137 rev 11

D28 — Deploy Build Verify Pack — Agent Prompt (Tier 1: Build Verify Only)

17 min read Revision 11
dieu28promptdeploybuild-verifyphase-1b-followuptier-12026-05-10

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)

  1. Verify generated map artifact (commit 0947613) hoạt động đúng khi build
  2. Verify 3 consumer file changes (commit d2db418) typecheck pass
  3. Verify server import alias (~/generated/... từ server/api/) hoạt động
  4. Document deploy mechanism (KHÔNG execute) cho follow-up pack
  5. 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_ARTIFACT
  • node_modules/ directory → STOP UNEXPECTED_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=false
  • rollback_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