This commit is contained in:
delete 2026-06-10 20:51:17 +03:00
commit b15b95781c
108 changed files with 14802 additions and 0 deletions

View file

@ -0,0 +1,45 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 01 - Foundation
Date: 2026-04-13
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/01-foundation.md`
- implementation files under `cmd/server`, `internal/app`, `internal/config`, `internal/http`, `web/templates`, `web/static`, and `migrations`
- `go test ./...` -> passed
- `go build -o /tmp/update-server ./cmd/server` -> passed
- live smoke checks against `127.0.0.1:18080`:
- `GET /healthz` -> `200 OK`
- `GET /` -> `200 OK`
- `GET /admin` -> `200 OK`
- `GET /api/v1` -> `200 OK`
## Findings
No blocking findings.
The stage stays within the agreed scope, the server boots successfully, the route scaffolding is present, and the template/static foundation is ready for Agent 02.
## Required Fixes
None.
## Optional Improvements
- Add a small smoke-test suite for the foundation routes in a later stage once the HTTP surface becomes more stable.
- Initialize a git repository if you want future validators to compare diffs with `git status` and `git diff`.
## Status
`APPROVED`

View file

@ -0,0 +1,54 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 02 - Database And Migrations
Date: 2026-04-14
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/02-database.md`
- previous validation report: `/Users/delete/projects/update_server/docs/agents/validation/01-foundation-validation.md`
- implementation files under `cmd/migrate`, `internal/db`, `internal/config`, `internal/app`, `internal/http`, and `migrations`
- `.gitignore` and `Justfile`
- `GOCACHE=/tmp/go-build-agent02 GOMODCACHE=/tmp/go-mod-agent02 go test ./...` -> passed
- `GOCACHE=/tmp/go-build-agent02 GOMODCACHE=/tmp/go-mod-agent02 go build -o /tmp/update-server-agent02-bin ./cmd/server` -> passed
- `GOCACHE=/tmp/go-build-agent02 GOMODCACHE=/tmp/go-mod-agent02 go build -o /tmp/update-migrate-agent02-bin ./cmd/migrate` -> passed
- `DATA_DIR=/tmp/update-server-agent02 APP_BASE_URL=http://127.0.0.1:18080 /tmp/update-migrate` -> passed
- live smoke checks against `127.0.0.1:18081` after starting `/tmp/update-server-agent02-bin` with a fresh `DATA_DIR`:
- `GET /healthz` -> `200 OK` with `"database":"ok"`
- `GET /` -> `200 OK`
- `GET /api/v1` -> `200 OK`
## Findings
No blocking findings.
The stage satisfies the agreed scope:
- the SQLite schema covers the required tables;
- migrations are present and executable;
- migration checksum tracking is implemented and tested;
- the server startup path opens SQLite and auto-applies migrations;
- the health endpoint now reflects database readiness.
## Required Fixes
None.
## Optional Improvements
- Add explicit tests for `scope_mode` transition guard behavior, not just incompatible access-row insertion.
- Update the small home-page eyebrow copy from `Foundation Stage` to something database-specific for consistency.
## Status
`APPROVED`

View file

@ -0,0 +1,57 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 03 - Authentication And Admin Sessions
Date: 2026-04-14
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/03-auth.md`
- previous validation report: `/Users/delete/projects/update_server/docs/agents/validation/02-database-validation.md`
- implementation files under `internal/auth`, `internal/db`, `internal/http`, `internal/app`, `internal/config`, and `web/templates`
- `GOCACHE=/tmp/go-build-auth-validate GOMODCACHE=/tmp/go-mod-auth-validate go test ./...` -> passed
- `GOCACHE=/tmp/go-build-auth-validate GOMODCACHE=/tmp/go-mod-auth-validate go build -o /tmp/update-server-auth-validate ./cmd/server` -> passed
- `GOCACHE=/tmp/go-build-auth-validate GOMODCACHE=/tmp/go-mod-auth-validate go build -o /tmp/update-migrate-auth-validate ./cmd/migrate` -> passed
- live smoke checks against `127.0.0.1:18082` after starting `/tmp/update-server-auth-validate` with fresh bootstrap credentials and a fresh `DATA_DIR`:
- `GET /admin` -> `303 See Other` to `/admin/login`
- `GET /admin/login` -> `200 OK`
- `POST /admin/login` -> `303 See Other` with session cookie
- `GET /admin` with valid cookie -> `200 OK`
- SQLite inspection confirmed `sessions.token_hash` stores the SHA-256 of the cookie token, not the raw token
- `POST /admin/logout` -> `303 See Other`
- `GET /admin` with the old cookie after logout -> `303 See Other` to `/admin/login`
- SQLite inspection confirmed the session row was invalidated
## Findings
No blocking findings.
The stage satisfies the agreed scope:
- bootstrap admin creation is wired from environment configuration;
- passwords are hashed with bcrypt;
- session tokens are generated securely and stored hashed in SQLite;
- the `/admin` route group is protected by session middleware and role checks;
- login and logout behavior works in live validation, including old-cookie rejection after logout.
## Required Fixes
None.
## Optional Improvements
- Decide explicitly in a later stage whether the login endpoint should stay generic for any active user session or reject non-admin roles up front for the current admin-only UI.
- Add CSRF protection when the security-hardening stage begins, especially for `POST /admin/logout` and future admin forms.
## Status
`APPROVED`

View file

@ -0,0 +1,62 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 04 - Projects, Tags, And Releases
Date: 2026-04-14
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/04-projects-releases.md`
- previous validation report: `/Users/delete/projects/update_server/docs/agents/validation/03-auth-validation.md`
- implementation files under `internal/db`, `internal/http`, `internal/releases`, `internal/storage`, `internal/slug`, `internal/app`, `internal/config`, and `web/templates`
- `GOCACHE=/tmp/go-build-agent04-validate GOMODCACHE=/tmp/go-mod-agent04-validate go test ./...` -> passed
- `GOCACHE=/tmp/go-build-agent04-validate GOMODCACHE=/tmp/go-mod-agent04-validate go build -o /tmp/update-server-agent04-validate ./cmd/server` -> passed
- `GOCACHE=/tmp/go-build-agent04-validate GOMODCACHE=/tmp/go-mod-agent04-validate go build -o /tmp/update-migrate-agent04-validate ./cmd/migrate` -> passed
- live smoke checks against `127.0.0.1:18083` after starting `/tmp/update-server-agent04-validate` with fresh bootstrap credentials and a fresh `DATA_DIR`:
- `GET /admin/projects` without session -> `303 See Other` to `/admin/login?next=%2Fadmin%2Fprojects`
- `POST /admin/login` -> `303 See Other` with session cookie
- `GET /admin/projects` with session -> `200 OK`
- `POST /admin/projects` -> project created
- `POST /admin/tags` -> tag created
- `POST /admin/projects/1/tags` -> tag attached
- `POST /admin/projects/1/releases` with multipart file upload -> `303 See Other`
- SQLite inspection confirmed project, tag, project-tag link, and release metadata rows
- filesystem inspection confirmed artifact saved under `DATA_DIR/artifacts/...`, outside `web/static`
- checksum of stored artifact matched `releases.checksum_sha256`
- `POST /admin/tags/1/delete` while tag was still attached -> redirected with `tag-in-use`
- `POST /admin/projects/1/archive` -> project became archived in SQLite and UI
## Findings
No blocking findings.
The stage satisfies the agreed scope:
- protected admin CRUD flows exist for projects and tags;
- project-tag assignment works;
- release uploads are stored under the private artifact directory;
- release metadata is persisted with sanitized filename, checksum, size, content type, storage path, and uploader linkage;
- archive and tag-in-use protection behaviors work in live validation.
## Required Fixes
None.
## Optional Improvements
- Add an explicit unit or integration test for rejecting uploads that exceed `MAX_UPLOAD_BYTES`.
- Consider surfacing a success flash on the projects list page for newly created items instead of only redirecting to detail pages.
- Add release disable/delete flows in a later stage when the product needs release lifecycle management beyond upload.
## Status
`APPROVED`

View file

@ -0,0 +1,64 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 05 - API Keys And Access Control
Date: 2026-04-14
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/05-api-keys.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/05-api-keys-fix.md`
- previous stage validation report: `/Users/delete/projects/update_server/docs/agents/validation/04-projects-releases-validation.md`
- implementation files under `internal/apikeys`, `internal/db`, `internal/http`, `internal/app`, and `web/templates`
- `GOCACHE=/tmp/go-build-agent05-revalidate GOMODCACHE=/tmp/go-mod-agent05-revalidate go test ./...` -> passed
- `GOCACHE=/tmp/go-build-agent05-rebuild GOMODCACHE=/tmp/go-mod-agent05-rebuild go build -o /tmp/update-server-agent05-revalidate ./cmd/server` -> passed
- `GOCACHE=/tmp/go-build-agent05-remigrate GOMODCACHE=/tmp/go-mod-agent05-remigrate go build -o /tmp/update-migrate-agent05-revalidate ./cmd/migrate` -> passed
- live smoke checks against `127.0.0.1:18085` after starting `/tmp/update-server-agent05-revalidate` with a fresh `DATA_DIR`:
- `GET /healthz` -> `200 OK`
- `GET /admin/api-keys` without session -> `303 See Other` to `/admin/login?next=%2Fadmin%2Fapi-keys`
- `POST /admin/login` -> `303 See Other` with session cookie
- `POST /admin/projects` -> project created
- `POST /admin/tags` -> tag created
- `POST /admin/projects/1/tags` -> tag attached
- `POST /admin/api-keys` -> `200 OK` with `Cache-Control: no-store, private, max-age=0`, `Pragma: no-cache`, and `Expires: 0`
- the create response showed the raw key once and also showed the persisted saved values immediately: name, description, selected scope mode, permissions, selected tag rule, and effective access preview
- `GET /admin/api-keys/1` after creation -> `200 OK`, raw key no longer present in HTML
- SQLite inspection confirmed only `key_hash` was stored and confirmed the persisted tag scope row in `api_key_tag_access`
## Findings
No blocking findings.
The previously reported issues are fixed:
- the secret-bearing creation response is explicitly marked non-cacheable;
- the immediate post-create detail page is hydrated from persisted data while still showing the raw key only on that one response.
The stage now satisfies the agreed scope:
- API keys are generated securely and stored hashed;
- admin UI supports create, update, and revoke flows;
- allow-list and deny-list groundwork is in place for both projects and tags;
- middleware and scope evaluation are covered by tests and the create-flow regressions are fixed.
## Required Fixes
None.
## Optional Improvements
- Consider a future POST-Redirect-GET plus short-lived flash-secret design if you want to avoid browser refresh resubmitting the create form while still keeping the raw key out of persistent storage.
- Later client API validation should explicitly exercise disabled and expired keys through the public `/api/v1` endpoints once Agent 06 wires them in.
## Status
`APPROVED`

View file

@ -0,0 +1,77 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 06 - Client API And Admin UI
Date: 2026-04-15
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/06-client-api-ui.md`
- previous stage validation report: `/Users/delete/projects/update_server/docs/agents/validation/05-api-keys-validation.md`
- implementation files under `internal/http`, `internal/db`, `internal/releases`, `internal/storage`, `web/templates`, and `web/static`
- `GOCACHE=/tmp/go-build-agent06-validate GOMODCACHE=/tmp/go-mod-agent06-http go test ./...` -> passed
- `GOCACHE=/tmp/go-build-agent06-build-validate GOMODCACHE=/tmp/go-mod-agent06-http go build -o /tmp/update-server-agent06-validate ./cmd/server` -> passed
- `GOCACHE=/tmp/go-build-agent06-migrate-validate GOMODCACHE=/tmp/go-mod-agent06-http go build -o /tmp/update-migrate-agent06-validate ./cmd/migrate` -> passed
- live smoke checks against `127.0.0.1:18086` after starting `/tmp/update-server-agent06-validate` with a fresh `DATA_DIR`:
- `GET /healthz` -> `200 OK`
- `GET /api/v1` -> `200 OK` with public JSON index documenting bearer auth and the client routes
- `GET /api/v1/projects` without bearer token -> `401 Unauthorized` with `WWW-Authenticate: Bearer`
- admin login succeeded and a fresh test dataset was created:
- active projects: `desktop-app`, `mobile-app`
- archived project: `legacy-app`
- releases created for desktop, mobile, and legacy projects
- tag-scoped API key with `can_download`
- API key without `can_download`
- expired API key
- `GET /api/v1/projects` with the allowed tag-scoped key -> `200 OK`, returning only active authorized project `desktop-app`
- `GET /api/v1/projects` with key lacking `can_download` -> `403 Forbidden`
- `GET /api/v1/projects` with expired key -> `401 Unauthorized`
- `GET /api/v1/projects/desktop-app/releases/latest` with allowed key -> `200 OK`, returning latest active desktop release `1.1.0 / build-2`
- `GET /api/v1/projects/mobile-app/releases/latest` with allowed key -> `404 Not Found`
- `GET /api/v1/releases/3` for out-of-scope mobile release -> `404 Not Found`
- `GET /api/v1/releases/4` for archived-project release -> `404 Not Found`
- `GET /api/v1/releases/2` with allowed key -> `200 OK`, returning authorized release metadata
- `GET /api/v1/releases/2/download` with allowed key -> `200 OK`, streamed `desktop-release-1.1.0` with `Content-Disposition: attachment; filename=desktop-app-1.1.0.zip`
- `GET /admin/projects/1` with admin session -> `200 OK`, page showed `/api/v1/projects/desktop-app/releases/latest`, `/api/v1/releases/2`, and `/api/v1/releases/2/download`
- `GET /admin/api-keys/1` with admin session -> `200 OK`, page showed bearer-auth quick-start guidance and accessible client API paths
- SQLite inspection of `/tmp/update-server-agent06-live/db.sqlite` confirmed:
- latest desktop release persisted as release ID `2`
- mobile release persisted as release ID `3`
- archived-project release persisted as release ID `4`
- validation API keys persisted with the expected permission and expiry states
## Findings
No blocking findings.
The stage satisfies the agreed scope:
- the public `/api/v1` index is usable and documents the client routes;
- bearer-authenticated client endpoints enforce API key authentication and `can_download`;
- client project listing returns only active authorized projects;
- latest-release lookup, metadata lookup, and artifact download work for authorized resources;
- out-of-scope and archived resources are hidden behind `404`;
- downloads stream from private artifact storage instead of exposing static URLs;
- admin pages expose the new client API paths and quick-start guidance.
## Required Fixes
None.
## Optional Improvements
- If the product later needs richer updater logic, add support for semantic-version comparison or explicit release channels instead of using newest persisted `created_at` as the definition of “latest”.
- Agent 07 should harden the now-working client API with security headers, rate limiting, CSRF coverage for admin POST forms, and deployment-ready reverse proxy guidance.
## Status
`APPROVED`

View file

@ -0,0 +1,88 @@
# Validation Report Template
## Validator
Name: Codex Validation Agent
Stage Reviewed: Agent 07 - Security And Deployment Hardening
Date: 2026-04-15
## Reviewed Inputs
- `/Users/delete/projects/update_server/docs/agents/WORKFLOW.md`
- `/Users/delete/projects/update_server/PRODUCT_SPEC.md`
- `/Users/delete/projects/update_server/IMPLEMENTATION_PLAN.md`
- `/Users/delete/projects/update_server/DEVELOPMENT_WORKFLOW.md`
- `/Users/delete/projects/update_server/docs/agents/OPERATOR_QUICKSTART_RU.md`
- `/Users/delete/projects/update_server/docs/agents/handoffs/07-security-deploy.md`
- previous stage validation report: `/Users/delete/projects/update_server/docs/agents/validation/06-client-api-ui-validation.md`
- implementation files under `internal/config`, `internal/app`, `internal/db`, `internal/auth`, `internal/http`, `web/templates`, `deploy`, and root deployment files
- `GOCACHE=/tmp/go-build-agent07-validate GOMODCACHE=/tmp/go-mod-agent06-http go test ./...` -> passed
- `GOCACHE=/tmp/go-build-agent07-build GOMODCACHE=/tmp/go-mod-agent06-http go build -o /tmp/update-server-agent07-validate ./cmd/server` -> passed
- `GOCACHE=/tmp/go-build-agent07-migrate GOMODCACHE=/tmp/go-mod-agent06-http go build -o /tmp/update-migrate-agent07-validate ./cmd/migrate` -> passed
- `command -v docker` -> command not available in this environment, so `docker compose config` and container runtime checks could not be executed here
- live smoke checks against an HTTP-configured hardened server on `127.0.0.1:18088`:
- `GET /admin/login` -> `200 OK` with:
- `Cache-Control: no-store, private, max-age=0`
- `Content-Security-Policy`
- `X-Frame-Options: DENY`
- `X-Content-Type-Options: nosniff`
- `Referrer-Policy: no-referrer`
- `Permissions-Policy`
- `Cross-Origin-Opener-Policy: same-origin`
- `Cross-Origin-Resource-Policy: same-origin`
- `Vary: Cookie`
- CSRF cookie scoped to `/admin`, `HttpOnly`, `SameSite=Strict`
- `POST /admin/login` without CSRF token -> `403 Forbidden`
- `POST /admin/login` with valid CSRF token -> `303 See Other` with:
- session cookie scoped to `/admin`
- `HttpOnly`
- `SameSite=Lax`
- rotated CSRF cookie scoped to `/admin`
- `GET /api/v1/projects` without bearer token -> `401 Unauthorized` with:
- `Cache-Control: no-store, private, max-age=0`
- `Vary: Authorization`
- shared security headers
- created a download-capable API key through the hardened admin flow and verified:
- first two `GET /api/v1/projects` requests -> `200 OK`
- third request -> `429 Too Many Requests` with `Retry-After: 1`
- changing `X-Forwarded-For` between those requests did not bypass the rate limit while `TRUST_PROXY_HEADERS` remained false, confirming socket-address behavior in practice
- live smoke checks against an HTTPS-configured hardened server on `127.0.0.1:18089` with `APP_BASE_URL=https://updates.example.com`:
- `GET /admin/login` -> `200 OK` with `Strict-Transport-Security: max-age=31536000`
- CSRF cookie carried `Secure`, `Path=/admin`, `HttpOnly`, `SameSite=Strict`
- `POST /admin/login` with valid CSRF token -> `303 See Other` with session cookie carrying `Secure`, `Path=/admin`, `HttpOnly`, `SameSite=Lax`
- static review of deployment artifacts:
- `Dockerfile`
- `docker-compose.yml`
- `deploy/Caddyfile.example`
- `deploy/nginx.update-server.conf.example`
- `deploy/update-server.env.example`
- `docs/DEPLOYMENT.md`
## Findings
No blocking findings.
The stage satisfies the agreed scope:
- admin and protected client routes emit sane security defaults;
- CSRF protection is enforced on admin POST flows;
- cookies are scoped to `/admin` and switch to `Secure` when the public base URL is HTTPS;
- login and protected client API rate limits work;
- trusted proxy handling is opt-in;
- deployment and backup or restore documentation is present and coherent with the current architecture;
- artifacts remain private and continue flowing through authenticated application endpoints.
## Required Fixes
None.
## Optional Improvements
- Run `docker compose up --build` and one reverse-proxy example on the real target host before first production exposure, since Docker was unavailable in this validation environment.
- If you later run multiple app instances, replace the current in-memory rate limiter with a shared store-backed or proxy-backed limiter.
## Status
`APPROVED`

View file

@ -0,0 +1,13 @@
# Validation Directory
Save one validation markdown file here after every validation pass.
Naming convention:
- `01-foundation-validation.md`
- `02-database-validation.md`
- `03-auth-validation.md`
- `04-projects-releases-validation.md`
- `05-api-keys-validation.md`
- `06-client-api-ui-validation.md`
- `07-security-deploy-validation.md`