Files
distribution/PLAN.md
agra 7176e63503 plan: re-evaluate against current sx (2026-06-11)
sx delivered most of the foundation since the plan was written: alias
re-exports instead of pub, the modules/std.sx facade barrel, and native
std fs/process/json/cli/hash/log/test/socket/mem. Replace the 'sx
Foundation Work' section with as-built status + remaining gaps, mark
Phase 0 done / Phase 1 partial, note the superseded subplan-01 slices,
and drop the retired flow-harness execution contract (subplan 08, roles,
checkpoint files).
2026-06-11 23:04:10 +03:00

11 KiB
Raw Blame History

Distribution Platform in sx

Goal

Build an App Store-like distribution platform in sx, but not limited to iOS apps. It should distribute mobile, desktop, and server/client artifacts through a CI-friendly release workflow.

Supported targets for the first product direction:

  • iOS: IPA metadata, TestFlight links, Enterprise/MDM manifests, artifact-only downloads
  • Android: APK first, AAB later
  • macOS: app archives, dmg/pkg metadata, signing and notarization status
  • Linux: tarballs first, then deb/rpm/AppImage metadata
  • Windows: zip/installer first, then MSIX/signing metadata

The main commands are:

  • distd: the HTTP API, install page, and artifact server
  • dist: the CI/admin CLI

The release workflow must be easy to integrate into CI. A CI job should be able to upload artifacts, create a release, attach platform variants, promote a channel, and receive machine-readable JSON output.

Product code should live in sx. C or system APIs are acceptable only as thin platform backends for capabilities that sx cannot express yet.

Product Shape

This is an operational distribution tool first, not a public marketplace. The initial product should feel like a release console: quiet, dense, fast to scan, and optimized for repeated internal/private release work.

Core principles:

  • CI is the primary writer.
  • Humans inspect, promote, revoke, download, and audit.
  • Releases are immutable.
  • Channels are mutable pointers to releases.
  • Artifacts are content-addressed and never silently replaced.
  • Every upload, publish, promotion, token change, and deletion writes an audit event.
  • The first version should be understandable from the filesystem and SQLite database during development.

Users And Actors

  • CI runner: publishes releases with dist ci publish.
  • Release manager: promotes channels, checks validation, and reads audit logs.
  • Developer/tester: downloads the current artifact for a platform/channel.
  • Admin: creates apps, manages tokens, and configures identity constraints.
  • distd: server/API/artifact store.
  • dist: CLI for CI and local admin work.

Core Concepts

App:

  • Product being distributed.
  • Owns identity rules, allowed platforms, releases, channels, and tokens.

Release:

  • Immutable version/build record for one app.
  • Contains one or more platform artifacts.

Artifact:

  • Uploaded file for a platform.
  • Stored by digest and linked to release metadata.

Channel:

  • Mutable pointer such as stable, beta, internal, nightly.
  • Promotion changes the pointer, not the release.

Token:

  • Scoped credential for CI and automation.
  • Stored hashed, expires or can be revoked.

Audit event:

  • Immutable record of important actions.

Main Workflows

CI publish:

  1. CI builds artifacts.
  2. CI writes or updates dist.json.
  3. CI runs dist ci publish --server "$DIST_SERVER" --token "$DIST_TOKEN" --manifest dist.json --json.
  4. dist validates the manifest and streams artifact uploads.
  5. distd validates metadata and stores artifacts by digest.
  6. The release is published.
  7. A requested channel is promoted if policy allows it.
  8. CI receives JSON with release ids, artifact ids, digests, and URLs.

Human release management:

  1. Release manager opens the admin UI.
  2. They inspect release status, artifact validation, and audit history.
  3. They promote, rollback, revoke tokens, or download artifacts.

Install/download:

  1. User opens an app/channel install page.
  2. Platform detection chooses the most relevant artifact or install path.
  3. The page shows accurate platform-specific actions and metadata.
  4. Access policy determines whether the user can download or install.

iOS Install Policy

iOS needs special handling. The platform must not imply that a normal iPhone can install an arbitrary IPA from a web page.

Supported iOS modes:

  • TestFlight: store a TestFlight link and open Apple's install flow.
  • Enterprise/MDM: serve a valid HTTPS manifest plist for enrolled devices.
  • Artifact only: allow authenticated IPA download, without presenting it as a normal mobile install action.

This distinction must be visible in both the API model and admin/install UI.

Architecture Overview

The intended stack is:

sx language and std primitives
  -> infra libraries: http, json, hashing, storage, db, auth, archive
  -> distribution domain: app, artifact, release, channel, token, audit
  -> interfaces: CLI, HTTP API, install pages, admin UI
  -> deployment: Docker image, NAS-friendly config, persistent data volume

Storage direction:

  • SQLite first.
  • Local filesystem artifact storage first.
  • Object storage adapter later.

Deployment direction:

  • Docker/OCI image.
  • One persistent /data volume for database, artifacts, uploads, config, and logs.
  • One HTTP port.
  • /healthz endpoint.
  • Runs behind a reverse proxy for TLS.
  • Runs as a non-root user.
  • UGREEN NAS deployment through Docker/Container Manager is a first-version requirement.

sx Foundation Status

Re-evaluated 2026-06-11 against the current sx tree. The original foundation asks have largely landed, with one design difference: sx has no pub keyword. Visibility is import-scoped; aliases are the re-export mechanism (print :: core.print), and a module's namespace tail carries one level into flat importers. modules/std.sx is the curated barrel this plan asked for.

Delivered in sx and used by this repo:

  • Module system: alias imports, alias re-exports, namespace barrels, one-level carry, dir-vs-file ambiguity rejection.
  • Error handling: the ! error channel with raise/catch/onfail (bindings take parens), ?T optionals.
  • std modules under modules/std/: core, fmt, list, mem (typed allocator helpers over alloc_bytes/dealloc_bytes), fs, process, socket (raw TCP), json, xml, cli, hash (streaming SHA-256), log (leveled, no timestamps yet), test (bare assert).

Still missing from sx — the forward wishlist; each item either blocks a later subplan or has an explicit local workaround:

  • Collections: HashMap (linear scan over List pairs meanwhile).
  • Strings: validated UTF-8 String, StringBuilder, explicit Unicode model (byte length, scalar values, grapheme clusters, and display width are distinct; invalid UTF-8 must not silently become a String).
  • Bytes and a full path module (only path_join/basename/dirname today).
  • Time/clock (publish shims time(2) via FFI), random, encodings (base64url, percent).
  • HTTP server/client and TLS boundary — blocks subplan 04 and remote publish (subplan 03 Slice 3).
  • SQLite — blocks subplan 02 Slice 2 (db.json stands in).
  • Archive inspection — blocks deep IPA/APK validation (subplan 05).
  • Config layering (env/file/CLI) and richer testing helpers.

Implementation Phases

Phase 0 - sx language/module prerequisites (done, as-built):

  • Delivered in sx via alias re-exports and namespace barrels; there is no pub keyword.

Phase 1 - standard library foundation (partial):

  • Delivered: fs, process, json, cli, hash, log, test, socket, mem.
  • Outstanding: HashMap, StringBuilder/Unicode model, time, random, encodings, HTTP/TLS, SQLite, archive (see "sx Foundation Status").

Phase 2 - product domain:

  • Define apps, releases, artifacts, channels, tokens, policies, and audit events.

Phase 3 - storage:

  • Add SQLite persistence and filesystem artifact storage.

Phase 4 - CLI first:

  • Make dist ci publish --manifest dist.json --json work before the admin UI.

Phase 5 - HTTP API:

  • Expose app, release, upload, download, channel, token, and audit endpoints.

Phase 6 - artifact validation:

  • Validate APK and IPA first, then desktop artifact metadata.

Phase 7 - channels and install pages:

  • Add promotion, rollback, download URLs, and platform-specific install pages.

Phase 8 - admin UI:

  • Build a dense operational UI for apps, releases, artifacts, tokens, settings, install pages, and audit logs.

Phase 9 - packaging:

  • Package distd and the admin UI into a Docker image suitable for UGREEN NAS.

CI Contract

The primary CI command should be:

dist ci publish \
  --server "$DIST_SERVER" \
  --token "$DIST_TOKEN" \
  --manifest dist.json \
  --json

The command should:

  1. Validate the manifest.
  2. Create or find the app.
  3. Create a draft release.
  4. Upload all artifacts with streaming SHA-256.
  5. Validate platform metadata.
  6. Publish the release.
  7. Promote the requested channel if specified.
  8. Print JSON containing release id, artifact ids, digests, and download URLs.

First Milestone

Milestone 1 is complete when:

  • Required sx language/std primitives exist or have explicit temporary boundaries.
  • distd can run locally.
  • dist ci publish can publish a release with at least APK and IPA artifacts.
  • Artifacts are stored by digest.
  • SQLite stores apps, releases, artifacts, channels, tokens, and audit events.
  • A channel can be promoted and rolled back.
  • Install/download pages accurately handle iOS, Android, and desktop artifacts.
  • The admin UI can inspect apps, releases, validations, tokens, and audit logs.
  • A Docker image can run on a UGREEN NAS with a persistent data volume.

Milestone 1 — Flow Step ↔ Subplan Slice Mapping

The flow decomposes subplan 02 (.agents/subplans/02-domain-and-storage.md) Slice 1 into two steps. This records that decomposition so each step's scope is verifiable from the repo:

  • P2.1 — domain structs + boundary validation. Delivers subplan-02 Core Structs (App, Platform, Release, Artifact, Channel, AuditEvent) and the boundary validation portion of Slice 1 — slug, version, channel name, platform id, and required-field presence, each with a distinct typed error. Per the PO ruling this includes Release.published_at and Artifact.metadata. Code lives under src/domain/; the acceptance test is tests/domain_validate.sx.
  • P2.3 — in-memory repository + persistence. Delivers the rest of Slice 1: the in-memory repository (create/list/get/update, find-by-slug, find-artifact-by-digest) plus db.json persistence.
  • Token is in neither P2.1 nor P2.3. Subplan 02 lists Token under Core Structs, but its delivery slice is Slice 5 — Token Security (generation, hashing at rest, scopes, expiration/revocation). It is out of the Slice-1 steps above.

Non-goals For Version 1

  • Public marketplace payments.
  • Reviews and ratings.
  • Organization billing.
  • Sophisticated staged rollout targeting.
  • CDN integration.
  • Full signing/notarization automation.
  • Object storage.
  • Postgres.

Detailed Execution

PLAN.md is the overview. Slice breakdowns live in .agents/subplans/ (0107). The active milestone slice plan and step progress live in current/ (PLAN.md, CHECKPOINT-DISTRIBUTION.md).

The multi-agent flow harness that originally executed this plan is retired; work proceeds directly in-session, branch-based, with make test green at each step boundary.