Skip to content

Implement authenticated immutable resource manifests and streaming #76

Description

@zoeyrose

Parent: atrinik/atrinik#314

Consumes content-toolkit#16 and coordinates with server#33, server#36, protocol#10, client#32, content#44, resources#14, and renderer#6.

Outcome

Pin and validate one complete immutable content/resource release at startup, advertise only its authenticated client-visible manifest projection, and serve allowlisted resource blobs/packs through Game Protocol 1 without blocking gameplay.

server#33 explicitly leaves resource streaming to a separate protocol/client/server issue, but the Go server backlog currently has no server-side owner. This issue fills that gap.

Ownership boundary

The server consumes released artifacts; it does not author, compile, repack, or atlas them.

  • content-toolkit and release publishers own stable resource/spriteset/pack catalogs, deterministic bytes, compatibility coordinates, and license manifests.
  • protocol owns manifest negotiation and resource request/chunk/resume/cancel stream contracts.
  • The client owns trust-scoped disk cache, verification, eviction, prefetch, and renderer-provider publication.
  • The renderer owns decode/upload queues, GPU caches, atlas/page selection, UVs, and residency.
  • The server owns release admission, the immutable advertised snapshot, authorization/disclosure projection, bounded serving, fair scheduling, reload lifetime, and operational metrics.

The server maps stable logical resource IDs to immutable blob/pack/member claims supplied by the release. It must never choose archive grouping, sprite UVs, texture pages, renderer materials, or GPU layout dynamically.

Startup admission and snapshots

  • Require exact repository/release/content/toolkit/schema/resource coordinates, complete-manifest digest, pack/blob/member digests and sizes, dependency graph, features, media/distribution classes, and required notice identities.
  • Validate the complete manifest graph and every server-served path/object before reporting readiness. Reject unknown required features, cycles, duplicate IDs/ranges, missing dependencies, unsafe paths/links, nonregular files, bad bounds, digest/size mismatches, and incompatible content/protocol/resource coordinates.
  • Admit only explicitly client-visible data formats. Never advertise or serve native code, dynamic libraries, scripts, source maps containing private paths/data, plugins, shaders/WGSL, configuration overrides, credentials, server-only content, or mutable state.
  • Publish a versioned authenticated client-visible projection rather than exposing a source/release directory. Stable IDs and digests—not operator paths—are the request surface.
  • Keep each admitted snapshot immutable for the lifetime of sessions/transfers that reference it. A failed reload leaves the previous complete snapshot active; an accepted transition is atomic and has explicit session/cache compatibility behavior.
  • Do not require a source checkout, Python/Rust compiler, toolkit process, general archive extraction, or content mutation at runtime.

Resource service

  • Implement the protocol#10 manifest and request/response/chunk/commit/cancel/resume state machines on dedicated resource streams integrated with server#33's QUIC scheduler.
  • Enforce exact per-resource, per-pack, per-range, per-session, per-server, concurrency, queue, bandwidth/token, retry, lifetime, and aggregate-memory/file-descriptor bounds before work is admitted.
  • Validate member/range requests against the immutable index. Never permit arbitrary path or byte-range reads outside declared members/chunks.
  • Prioritize gameplay/control progress over bulk transfers while providing bounded fairness among resource streams. Slow or malicious peers cannot pin snapshots, buffers, descriptors, or workers indefinitely.
  • Support cancellation, reset, reconnect/resume, stale-manifest rejection, not-modified/content-addressed cache claims, and clean shutdown without partial commits.
  • If an operator-managed HTTPS/CDN origin is supported, authenticate all size/digest/type metadata over GP1, define immutable URL/cache behavior, require safe TLS policy, and retain a bounded protocol fallback. The Go server must not silently become an ambient HTTP file server.
  • Stream verified stored bytes/ranges without decoding images or extracting general archives on request paths. Bound any required decompression and verify the exact post-transform claim before exposure.

Observability and operations

Expose bounded-cardinality metrics for admitted snapshot identity, manifest/resource requests, cache/not-modified responses, active streams, queued work, bytes, cancellations/resumes, rejection class, fairness/backpressure, and latency. Never label metrics/logs with unbounded resource IDs, paths, account names, tokens, or client-controlled text.

Document atomic release staging, readiness, reload/rollback, retention of referenced snapshots, disk/memory/file-descriptor budgets, CDN publication ordering if applicable, and shutdown cleanup.

Acceptance criteria

  • The server independently validates released positive/negative manifest and pack fixtures shared with protocol/toolkit/client; a release either becomes the complete active resource snapshot or leaves the prior snapshot untouched.
  • Fixtures cover empty/large manifests, stable logical IDs, shared dependencies, packs and bounded member/range claims, unsupported features, cycles/duplicates/overlaps, missing members, wrong digest/size/type, corruption/truncation, stale coordinates, excessive expansion, unsafe paths/links, and prohibited executable/script/shader data.
  • Request state-machine tests cover unknown/stale claims, chunk ordering, resume, duplicate/replay, cancellation/reset, reconnect, slow readers, timeouts, queue pressure, rate limits, disconnect, reload during transfer, and graceful drain.
  • Sustained maximum-admitted resource downloads from multiple clients do not starve or materially regress handshake, input, authoritative tick, and gameplay/state-stream progress; fairness and memory/descriptor ceilings are measured.
  • Authenticated server identity and manifest/release changes cannot poison or reuse another trust namespace accidentally; the client receives enough immutable coordinates to apply client#32 atomically.
  • Bad reloads, disk errors, removed files, and partial staging never expose a partial manifest or invalidate the prior good snapshot. Referenced old snapshots retire only under documented bounded policy.
  • A minimal wrapper replacement profile can start from pinned released content/resources, fetch one shared/common pack and one spriteset-dependent pack through a generated Rust client fixture, render-provider verify the members, and clean up without a sibling source checkout or runtime compiler.
  • tools/validate.sh and git diff --check pass with Go/Rust conformance fixtures, fuzz coverage for parsers/state machines, and fault-injection coverage for serving and reload.

Dependencies and parallelization

Depends on protocol#10 and the released manifest/pack fixture from content-toolkit#16/content#44/resources#14. It composes with server#33's transport scheduler and server#36's immutable gameplay catalog, but resource serving can be developed against a small synthetic released fixture while whole-corpus compilation proceeds.

New server code/tests are independent MIT work. Distributed media retain their exact license/notice metadata and stay external immutable data; no Classic implementation or GPL fixture may be copied without exact approved provenance.

Priority, blockers, and parallel delivery

Priority: P1 service foundation, P2 released integration. Begin immutable snapshot/admission work immediately against the synthetic content-toolkit#16 fixture; do not wait for the real corpus or a final container to implement bounded ownership and failure behavior.

Hard completion and integration blockers

Blocked server result Hard dependency Required handoff
GP1 wire integration protocol#10 Frozen manifest/request/chunk/resume/cancel/error state machines, limits, and Go/Rust fixtures
Gameplay-first resource scheduling server#33 QUIC stream-role/session scheduler, bounded fairness/backpressure, identity, reconnect, and drain interfaces
Real pack/member admission content-toolkit#16 released through content-toolkit#7 Versioned schemas/specs, canonical digests, bounds, indexes, and golden/negative fixture release
Complete pinned content/resource topology server#36, content#44, and resources#14 Compatible immutable gameplay catalog plus client-visible content/resource release coordinates and license inventories
Wrapper M2 integration proof atrinik#266 and atrinik#269 Replacement build adapters and isolated topology/state supervision

These dependencies block the named integration result, not all implementation. The snapshot model, validator, service interfaces, rate/fairness model, metrics, and failure tests can use a small synthetic fixture immediately.

Execution order

Phase Work Parallel work Gate
S0 — immutable snapshot/admission core Define internal manifest/member/pack claims, validate the complete graph, publish/retain/retire snapshots atomically, and model reload/rollback. Validator, snapshot lifecycle, filesystem admission, prohibited-type checks, metrics schema, fuzz corpus Bad input/disk/reload cannot disturb the prior snapshot; no network or compiler required
S1 — bounded service state machine Implement resource lookup, member/range validation, queues/budgets, cancellation, timeouts, fairness, and test transport against synthetic protocol/toolkit fixtures. Scheduler model, request parser, streaming reader, rate limits, slow-peer/fault tests Exact memory/descriptor/queue bounds and gameplay-priority assertions pass
S2 — GP1/QUIC integration Bind S1 to protocol#10 generated contracts and server#33 sessions/streams; add reconnect/resume/drain and authenticated manifest projection. Go/Rust conformance, fuzzing, metrics/diagnostics, optional CDN policy review Shared protocol fixtures pass; malformed/slow peers cannot starve gameplay
S3 — released artifact integration Admit content-toolkit#16/content#44/resources#14 release candidates and associate them atomically with server#36's gameplay catalog. Publisher validation and client#32 cache/provider work proceed concurrently No source checkout/runtime compiler; exact compatible coordinates and notice inventory required
S4 — wrapper and load proof Run one pinned replacement profile/topology/scenario with client#32/renderer#6, sustained resource traffic, reload/fault cases, and cleanup. Platform/package tests and soak analysis M2 latency/resource budgets pass and evidence feeds atrinik#271/#279

Parallelization and handoffs

  • S0 and most of S1 can proceed while protocol#10, server#33, and content-toolkit#16 are open.
  • After protocol fixture v1 freezes, S2 server work and client#32 transport/cache work proceed in parallel; neither implementation owns the other's domain model.
  • S3 publisher, server, and client/provider integrations proceed concurrently against the same immutable release candidate. A mismatch fails before startup/session publication.
  • Renderer#6 is a downstream verified-member consumer and can develop in parallel. Renderer#14's M4 UV/atlas optimization is not a server or M2 blocker.
  • Optional CDN work follows the authenticated GP1 metadata and bounded QUIC fallback; it cannot delay the baseline direct resource stream.

Completion handoff

Link the exact protocol/toolkit/content/resources/server/client/renderer versions and digests, fixture release, bounds, benchmark/load environment, wrapper profile/topology/state/scenario, results, logs/evidence, rollback behavior, and cleanup. Server#76 can close after the M2 admitted slice; whole-corpus convergence remains content-toolkit#9/atrinik#280.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    Status
    Inbox

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions