feat(api): .kc checkout packing + ETag caching (Phase 2) #142

Closed
opened 2026-02-18 20:58:38 +00:00 by forbes · 0 comments
Owner

Implement the checkout pipeline that packs server-side state into the silo/ directory before serving .kc files, as specified in KC_SERVER.md Section 5.

Depends on: #141 (Phase 1 -- commit extraction + metadata API)
Supports: SILO_VIEWPORT Phase 1-3

Checkout Pipeline (Section 5)

When a client downloads a .kc via GET /api/items/{partNumber}/file:

  1. Read the .kc file from disk
  2. Query DB for current server-side state
  3. Replace the silo/ directory entries in the ZIP:
    • manifest.json from item_metadata + items table
    • metadata.json from item_metadata.fields + tags + lifecycle
    • history.json from revisions table (last 20 revisions)
    • approvals.json from item_approvals + approval_signatures (if active ECO)
    • dependencies.json from item_dependencies
    • macros/*.py from item_macros
    • jobs/*.yaml from job_definitions (filtered by item type)
  4. Stream the repacked .kc to the client

Caching (Section 5.3)

  • ETag header: Computed from revision number + metadata updated_at. Support If-None-Match -> 304 Not Modified.
  • Lazy packing: Skip repacking if the stored blob's revision_hash matches current head AND item_metadata.updated_at is older than the blob's upload time.

Implementation scope

  • internal/kc/pack.go -- silo/ directory serializer, ZIP entry replacement
  • Modify existing file download handler to call pack pipeline for .kc files
  • Plain .fcstd files bypass packing (no silo/ directory)

Acceptance criteria

  • Downloading a .kc returns a file with silo/ entries reflecting current DB state
  • Metadata edited via web UI is reflected in the next download without re-commit
  • ETag caching returns 304 when nothing has changed
  • Lazy packing skips repack when blob is already current
  • Plain .fcstd downloads unchanged
Implement the checkout pipeline that packs server-side state into the silo/ directory before serving .kc files, as specified in [KC_SERVER.md](docs/KC_SERVER.md) Section 5. **Depends on:** #141 (Phase 1 -- commit extraction + metadata API) **Supports:** SILO_VIEWPORT Phase 1-3 ## Checkout Pipeline (Section 5) When a client downloads a .kc via `GET /api/items/{partNumber}/file`: 1. Read the .kc file from disk 2. Query DB for current server-side state 3. Replace the `silo/` directory entries in the ZIP: - `manifest.json` from item_metadata + items table - `metadata.json` from item_metadata.fields + tags + lifecycle - `history.json` from revisions table (last 20 revisions) - `approvals.json` from item_approvals + approval_signatures (if active ECO) - `dependencies.json` from item_dependencies - `macros/*.py` from item_macros - `jobs/*.yaml` from job_definitions (filtered by item type) 4. Stream the repacked .kc to the client ## Caching (Section 5.3) - **ETag header**: Computed from revision number + metadata updated_at. Support `If-None-Match` -> 304 Not Modified. - **Lazy packing**: Skip repacking if the stored blob's revision_hash matches current head AND item_metadata.updated_at is older than the blob's upload time. ## Implementation scope - `internal/kc/pack.go` -- silo/ directory serializer, ZIP entry replacement - Modify existing file download handler to call pack pipeline for .kc files - Plain .fcstd files bypass packing (no silo/ directory) ## Acceptance criteria - Downloading a .kc returns a file with silo/ entries reflecting current DB state - Metadata edited via web UI is reflected in the next download without re-commit - ETag caching returns 304 when nothing has changed - Lazy packing skips repack when blob is already current - Plain .fcstd downloads unchanged
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/silo#142