# Update Server - Implementation Strategy

## 1. Recommended stack

### Backend

- Go 1.24+
- Router: `chi` or `gin`
- HTML templates for admin UI, or server-rendered pages first
- Database: `SQLite`
- ORM/query layer: `sqlc`, `bun`, `gorm`, or plain `database/sql`
- Migrations: `golang-migrate` or `goose`
- Auth:
  - web admin via secure cookie session
  - client API via bearer API key

### My recommendation

For this project, a pragmatic Go stack would be:

- `chi` for routing;
- `database/sql` + `sqlc` or `bun`;
- `SQLite` with `modernc.org/sqlite` or `mattn/go-sqlite3`;
- server-rendered HTML templates for admin pages;
- `goose` for migrations.

Why this stack:

- simple to deploy;
- less JS and frontend complexity;
- good fit for an internal admin panel;
- easier to keep maintainable for a small self-hosted tool.

## 2. Quick glossary

`GUI`

- graphical user interface;
- here it simply means the admin web panel in a browser.

`chi`

- a small and fast HTTP router for Go;
- this is not `CI`;
- it helps map routes like `/api/v1/projects/{id}` to handlers.

`CI`

- continuous integration;
- automated checks that run on commits, for example tests, linting, or building Docker images.

`server-rendered HTML`

- the Go server itself generates HTML pages and returns them to the browser;
- this keeps the admin panel simpler than building a separate frontend app.

## 3. Architecture proposal

Suggested project structure:

```text
/cmd/server
/internal/app
/internal/http
/internal/auth
/internal/projects
/internal/releases
/internal/apikeys
/internal/users
/internal/tags
/internal/storage
/internal/db
/internal/config
/web/templates
/web/static
/migrations
/data
```

### Main modules

`projects`

- create/update/list/archive projects
- manage project tags

`releases`

- upload artifact
- compute checksum
- store metadata
- provide release lookup and download

`apikeys`

- generate secure random API keys
- hash and persist
- enforce permissions and project scope

`tags`

- CRUD for tags
- attach tags to projects
- resolve tag-based access rules

`users`

- admin authentication
- password hashing
- role checks

`storage`

- local filesystem storage abstraction
- future option to swap to S3-compatible storage

## 4. Suggested data model

Core tables:

- `users`
- `projects`
- `tags`
- `project_tags`
- `releases`
- `api_keys`
- `api_key_project_access`
- `api_key_tag_access`
- `sessions` if server-side sessions are used
- optionally `audit_logs`

### Example relations

- one `project` has many `releases`
- one `user` uploads many `releases`
- one `project` has many tags through `project_tags`
- one `api_key` can reference many projects through `api_key_project_access`
- one `api_key` can reference many tags through `api_key_tag_access`

Suggested key columns in `api_keys`:

- `scope_mode` with values:
  - `all_projects`
  - `project_allow_list`
  - `project_deny_list`
  - `tag_allow_list`
  - `tag_deny_list`

## 5. Permission strategy

Recommended first implementation:

- API key has boolean flags:
  - `can_download`
  - `can_upload`
  - `can_delete`
  - `can_manage_projects`
- API key has access mode:
  - `all_projects`
  - `project_allow_list`
  - `project_deny_list`
  - `tag_allow_list`
  - `tag_deny_list`
- linked projects stored in `api_key_project_access`
- linked tags stored in `api_key_tag_access`

Recommended evaluation rules:

- `all_projects`: allow every active project
- `project_allow_list`: allow only linked projects
- `project_deny_list`: allow every active project except linked projects
- `tag_allow_list`: allow projects matching at least one linked tag
- `tag_deny_list`: allow every active project except projects matching blocked tags

Recommended constraint for v1:

- each key uses exactly one scope mode at a time.

This supports whitelist, blacklist, and future grouping without building a full RBAC engine upfront.

## 6. API design strategy

Split API into two logical areas:

### Client API

Used by application clients:

- authenticate by bearer API key
- list accessible projects
- query latest release
- download release artifact

### Admin API

Used by web UI and optionally automation:

- manage projects
- manage tags
- manage releases
- manage API keys
- manage users

Keep both under `/api/v1`, but separate middleware and handlers clearly.

## 7. File upload strategy

Recommended upload flow:

1. admin uploads file;
2. backend stores temporary stream;
3. checksum is calculated;
4. file is moved into final artifact path;
5. release metadata is inserted into DB;
6. transaction/state is finalized.

Important safeguards:

- limit file size;
- sanitize filenames;
- prevent path traversal;
- avoid duplicate version collisions unless explicitly replacing;
- validate project exists before storing;
- store uploads outside any static web root;
- never execute or unpack uploaded files.

## 8. Security checklist

- hash passwords with `bcrypt` or `argon2id`
- hash API keys before storing
- show full API key only once
- secure cookies with `HttpOnly`, `Secure`, `SameSite`
- CSRF protection for admin forms
- upload size limits
- permission checks on every API endpoint
- request logging without leaking secrets
- rate limiting for login and API key endpoints
- store artifacts outside the web root
- serve downloads only after auth and permission checks
- set server timeouts: read, write, idle, header
- add security headers such as `Content-Security-Policy`, `X-Frame-Options`, `X-Content-Type-Options`
- terminate TLS at Caddy or Nginx
- optionally restrict admin UI by IP allow-list or VPN
- avoid shelling out to external tools for file processing
- keep dependencies updated and scan them periodically

## 9. Internet-facing deployment posture

If the server will be visible on the internet, this is the safe baseline:

- app listens only behind a reverse proxy;
- reverse proxy handles HTTPS certificates;
- admin UI uses strong password and optionally IP allow-list;
- SQLite file and artifacts live on a mounted persistent volume;
- no public directory listing for artifacts;
- uploads never become directly executable server-side content;
- logs and backups are stored separately from app code.

## 10. Development strategy

Recommended approach:

- develop locally on your Mac first;
- keep everything in one project directory;
- run the Go server natively for fast iteration;
- add Docker packaging once the core flows work locally;
- deploy to Proxmox only after the first end-to-end flow is stable.

Why local-first is better here:

- faster feedback loop;
- easier debugging;
- easier file upload testing;
- no need to fight remote networking while core logic is still changing.

Good compromise:

- write code locally on Mac;
- keep deployment target from day one in mind;
- periodically verify that the Docker image still builds.

## 11. Deployment strategy

Single container is realistic.

Recommended runtime layout:

- app binary in container
- reverse proxy in front of container
- mounted `/data` volume
- SQLite DB in `/data/db.sqlite`
- artifacts in `/data/artifacts`

### Environment variables

- `APP_ADDR`
- `APP_BASE_URL`
- `DATA_DIR`
- `SQLITE_PATH`
- `ADMIN_EMAIL`
- `ADMIN_PASSWORD`
- `SESSION_SECRET`

Recommended deployment target:

- Proxmox VM or LXC with Docker or Podman;
- app container plus reverse proxy;
- mounted volume for `/data`;
- regular backup of `/data`.

## 12. Delivery phases

### Phase 1 - Skeleton

- initialize Go module
- wire config
- HTTP server
- health endpoint
- migrations setup
- SQLite connection
- basic template rendering

### Phase 2 - Auth and admin bootstrap

- user table
- create initial admin user
- login/logout
- session middleware

### Phase 3 - Projects and releases

- projects CRUD
- project tags CRUD
- release upload
- release list/detail
- local artifact storage

### Phase 4 - API keys and access control

- API key generation
- hashed storage
- project white-list and black-list
- tag-based schema and access checks
- permission middleware

### Phase 5 - Client update API

- latest release endpoint
- release metadata endpoint
- download endpoint
- audit of last key usage

### Phase 6 - Hardening

- validation
- CSRF
- logging
- soft deletes
- basic audit logs
- reverse proxy config
- rate limiting
- Docker image and compose setup

## 13. Agent execution plan

If multiple AI agents or contributors will implement this, split work by vertical ownership.

### Agent 1 - Core platform

Owns:

- Go module setup
- config
- server bootstrap
- middleware skeleton
- Docker setup

### Agent 2 - Data layer

Owns:

- migrations
- schema
- repositories/queries
- SQLite integration
- tags and access-rule tables

### Agent 3 - Auth and users

Owns:

- admin login
- sessions
- password handling
- user management basics

### Agent 4 - Projects and releases

Owns:

- project CRUD
- tag assignment to projects
- release upload flow
- artifact storage abstraction
- checksum logic

### Agent 5 - API keys and client API

Owns:

- API key generation
- permission model
- whitelist/blacklist evaluation
- tag-based access evaluation
- client-facing release lookup and download endpoints

### Agent 6 - Admin UI

Owns:

- HTML templates
- forms
- tables/pages for projects, releases, keys, users, tags

### Agent 7 - Security and deployment hardening

Owns:

- secure headers
- rate limiting
- reverse proxy templates
- deployment hardening review

## 14. Recommended implementation order for agents

1. Agent 1 sets up application skeleton and app wiring.
2. Agent 2 defines schema and migrations.
3. Agent 3 implements admin auth.
4. Agent 4 implements projects, tags, and release storage.
5. Agent 5 implements API key model and client endpoints.
6. Agent 6 builds the admin UI on top of completed flows.
7. Agent 7 hardens internet-facing deployment paths.
8. Final pass integrates validation, tests, and Docker packaging.

## 15. Testing strategy

### Unit tests

- version selection logic
- permission checks
- API key hashing/lookup
- checksum generation
- tag scope matching

### Integration tests

- login flow
- create project
- attach tags to project
- upload release
- create API key
- fetch latest release via API key
- reject unauthorized project access
- reject blacklisted project or tag access

### Manual sanity tests

- upload file from admin UI
- download via curl using bearer API key
- restart container and verify persistence
- verify admin login rate limits
- verify artifacts are not directly exposed by URL guessing

## 16. My recommendations on product scope

To avoid overbuilding too early, I would start with:

- SQLite
- local filesystem storage
- server-rendered admin UI
- one file per release
- one admin role first, but schema ready for more users
- one scope mode per key
- project whitelist and blacklist in v1
- project tags in schema from day one

This version will already be useful and can stay very small operationally.

## 17. Nice first concrete milestone

The first milestone should be:

"Admin can log in, create a tagged project, upload a versioned file, create an API key with project or tag-based access, and a client can download the latest file using that key."

If that works end-to-end, the rest can be layered on safely.
