Skip to content

[Deploy-S7] Aspire Docker/Compose deploy target adapter (planning)#363

Merged
rickylabs merged 8 commits into
mainfrom
feat/deploy-s7-aspire
Jul 3, 2026
Merged

[Deploy-S7] Aspire Docker/Compose deploy target adapter (planning)#363
rickylabs merged 8 commits into
mainfrom
feat/deploy-s7-aspire

Conversation

@rickylabs

Copy link
Copy Markdown
Owner

Summary

PLANNING-ONLY draft for the Aspire Docker/Compose deploy target adapter (Deploy-S7). This PR
carries the harness research + plan artifacts only — no product code — and is a hard stop for a
separate-session PLAN-EVAL before any implementation slice.

Delivers an Archetype-7-conformant plan for netscript deploy docker|compose <verb>: a thin
deploy <target> router over a one-file Aspire cloud adapter that delegates plan/up to the
Aspire CLI (aspire publish / aspire deploy) against a compose-enabled generated apphost.mts,
and covers the full 7-op lifecycle (supported subset, no silent no-ops) with config surfaced as
Parameters__* and a denoland/deno:2 base.

Scope

Slices (planned — not yet implemented)

  • S1 config member (deploy.targets.docker|compose, spreads base, denoland/deno:2)
  • S2 port expansion 3-op → uniform 7-op contract
  • S3 core convention primitives (secrets + rollback, centralized)
  • S4 AppHost compose generation (addDockerComposeEnvironment + Deno container + publishAsDockerComposeService)
  • S5 Aspire compose adapter (one file, delegates via ProcessPort)
  • S6 thin docker/compose router sub-commands
  • S7 docs + arch-debt
  • S8 CI-safe E2E gate (compose-artifact emit + docker compose config)

Validation

  • Planning phase — no code, no gates run yet. Validation plan enumerated in plan.md
    (check/lint/unit/adapter-fake-ProcessPort/JSR dry-run/arch/scaffold-snapshot/e2e:cli scaffold.runtime).

Harness

  • Run dir: .llm/tmp/run/deploy-s7-aspire/ (research.md, plan.md, worklog.md).
  • Phase: plan — awaiting PLAN-EVAL (separate session). No implementation before PASS.

Open decisions for PLAN-EVAL

  1. Port 3-op→7-op expansion ownership (coordinate [Deploy-S6] Deno Deploy tier-1 adapter (marquee) #342/[Deploy-S3] WindowsServicePort -> OsServicePort + SystemdAdapter #339) — design-fixed (L1), merge-order only.
  2. docker + compose = two registry keys on one adapter (resolved).
  3. Merge-gate E2E = CI-safe artifact validation; live docker compose up boot opt-in (resolved, L8).
  4. F-DEPLOY-1/2 stay reviewed (not promoted to gated) this slice.

Drift / Debt

Closes #343
Refs #327

🤖 Generated with Claude Code

https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

…n (PLANNING-ONLY)

Planning artifacts for #343 [Deploy-S7]: Archetype-7 conformance, 7-op contract
mapping (delegating plan/up to the Aspire CLI), 8 ordered commit slices, gates,
risks, and open-decision sweep. No product code. Awaiting PLAN-EVAL.

Refs #343
Refs #327

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN
@rickylabs rickylabs added this to the 0.0.1-beta.3 milestone Jul 3, 2026
@rickylabs rickylabs added area:cli area:aspire area:deploy Deployment: CLI/Aspire deploy, targets, bare-metal epic:deployment Enterprise deployment framework epic priority:p1 High wave:v1 status:plan Harness plan phase labels Jul 3, 2026
rickylabs and others added 7 commits July 3, 2026 11:40
Add DockerComposeDeployTargetSchema spreading deployTargetBaseShape (no base
class, R-DEPLOY-4) plus compose/registry fields (projectName, outputPath,
registry, imageName), and wire deploy.targets.docker + deploy.targets.compose.
The base container docker sub-block (denoland/deno:2 default) is inherited via
spread and left on the base since resolveWindowsDeploy still consumes it.

Refs #343.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add AspireComposeDeployTarget: a one-file delegation shell over ProcessPort that
authors no compose YAML (A7/F-2). plan/emit -> `aspire publish --output-path`;
compose up -> `docker compose up -d` on the emitted project, docker up ->
`aspire deploy`; down/status/logs -> `docker compose`. Registered under two keys
(compose, docker) in the composition-root DeployTargetRegistry. Supports the
plan/emit/up/down/status/logs subset and declares rollback/secrets unsupported
(shared core conventions land with #341). Fake-ProcessPort tests assert per-op
argv and delegation. Uses @std/path/posix for stable, docker-friendly paths.

Refs #343.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add createTargetDeployCommand: a thin Cliffy router that parses --project-root
/--output-dir, resolves the adapter from the DeployTargetRegistry, and routes the
lifecycle verb straight to it — no target-specific logic (the adapter branches on
its key, R-DEPLOY-2). Verb subcommands are derived from the adapter's advertised
`operations`, so omitted ops (rollback/secrets) never surface. Output flows through
the presentation reporter (outputText/outputError), never raw console. Wire `docker`
and `compose` sub-commands into the deploy group alongside the legacy flat Windows
verbs (additive). Tests assert verb derivation and straight-through routing.

Refs #343.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Refs #343.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…as arch-debt (S7)

Add arch-debt entries DEPLOY-S7-APPHOST-COMPOSE-GEN (S4 deferred: apphost
compose-publishing generation is a shared cross-slice primitive, unvalidatable
without the Aspire+Docker toolchain, overlaps #342) and DEPLOY-SECRETS-ROLLBACK-CORE
(S3 blocked on #341/#364 core conventions). Record drift D7/D8 and the final slice
disposition in the run artifacts. The deploy.md prose update is held to land with
the S4 apphost-gen slice so docs describe a working docker/compose path.

Refs #343.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Refs #343.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rickylabs
rickylabs marked this pull request as ready for review July 3, 2026 11:47
@rickylabs
rickylabs merged commit c4def7d into main Jul 3, 2026
6 checks passed
rickylabs added a commit that referenced this pull request Jul 3, 2026
Rebase reconciliation: main's #364 drop-behavior test asserted the
{windows, linux} target set with `solaris` as the genuinely-unknown throwaway
key. Extend it for the deno-deploy member added by this branch — assert
`deno-deploy` is retained (org/app) alongside windows+linux and that `solaris`
is still dropped. Keeps the union honest post-rebase onto #363+#364.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN
rickylabs added a commit that referenced this pull request Jul 3, 2026
* docs(deploy): [Deploy-S6] research + plan for Deno Deploy tier-1 adapter (#342)

Planning-only harness run docs (research.md + plan.md) for the Deno Deploy
marquee target (D2). Grounds against #337 deploy.targets.* contract and #338
DeployTargetPort archetype; enumerates 4 commit slices, change map, fitness
gates, and open decisions (CLI-push default, CI auth) as NEEDS USER.

Refs #342 #327

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

* docs(deploy): [Deploy-S6] revise research+plan to Archetype-7 7-op contract (#342)

Rev 2 after peer FAIL_PLAN (B1): select Archetype 7 (composite Arch2+Arch6),
conform to the canonical 7-op deploy contract, record that the 3-op->7-op port
expansion is owned by #339/#340 (this slice CONSUMES it, does not redefine it),
re-baseline against merged main (#352 config + 3137e45 seed port already landed),
add the 7-op->Deno-Deploy op-mapping, and correct the dispatch lane to Opus 4.8
sub-agents. Still planning-only; awaits PLAN-EVAL.

Refs #342 #327
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

* chore(harness): record deploy-s6 rev-2 commit ledger (#342)

Refs #342 #327
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

* feat(deploy): [Deploy-S6] add deno-deploy config member (S1)

Add the `deploy.targets['deno-deploy']` config member to @netscript/config:
a `DenoDeployTarget` interface extending `DeployTargetBase` and a
`DenoDeployTargetSchema` (z.ZodType<DenoDeployTarget>, spread-composed on
`deployTargetBaseShape` per R-DEPLOY-4). Wires the `deno-deploy` key into
`DeployConfigSchema.targets` and exports the new type + schema from the public
surface. The explicit `z.ZodType` annotation preserves JSR fast-types.

Consumes the merged base (#352); does not touch the deploy port contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(harness): record S1 commit in deploy-s6 ledger

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(deploy): [Deploy-S6] add unstable-API preflight guard (S2)

Add a pure `scanUnstableApis` guard (D9 / research Finding 9) that flags
`--unstable-*`-requiring APIs before a `deno deploy` push, since Deno Deploy
rejects those flags. Detects features declared in `deno.json`'s `unstable`
list and direct unstable-API tokens (Deno.openKv/cron, BroadcastChannel,
Temporal) in supplied entrypoint sources. Pure by design: callers supply
already-read file contents so FS access stays out of the domain (A11/F-CLI-16);
the `plan` op wires this to an FS reader in S3. Best-effort (no transitive
graph walk); bound recorded for arch-debt in S4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(harness): record S2 + drift/worklog in deploy-s6 ledger

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(deploy): add Deno Deploy target adapter (7-op subset)

Implement the tier-1 Deno Deploy deployment-target adapter consuming the
canonical DeployTargetPort. Declares the supported op subset
plan/up/down/status/logs; rollback/secrets are omitted pending the deploy
core convention seam (#341/#364) rather than forked adapter-locally.

- DenoDeployTarget (domain): pure target running the unstable-API guard on
  plan/up; refuses production pushes with violations, warns on preview.
- DenoDeployCliAdapter (kernel/adapters): confines `deno deploy` shelling
  behind a ProcessPort (F-CLI-16); exported argv builders unit-tested.
- DenoDeployPreflightReader (kernel/adapters): FS reader feeding the pure
  guard with deno.json + entrypoint sources.
- Register `deno-deploy` in DEFAULT_DEPLOY_TARGETS wired at the app layer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(deploy): wire Deno Deploy target into CLI router + config resolver

Complete the Deno Deploy tier-1 target with its thin CLI reach and config
resolution (Deploy-S6 S4).

- resolveDenoDeployTarget: merge `deploy.targets['deno-deploy']` config with
  CLI flag overrides (flags win; prod defaults false) → ResolvedDenoDeployConfig.
- createDenoDeployTarget: single composition factory wiring the CLI adapter +
  preflight reader; registry and surface both consume it (no Deno.Command leaks
  into features/presentation — F-CLI-16).
- `netscript deploy deno-deploy <plan|up|down|status|logs>`: thin router reach
  (R-DEPLOY-2) mapping --org/--app/--prod/--entrypoint/--env-file/--dry-run onto
  the resolved config; all target logic stays in the domain/adapter layers.
- README permissions block (--allow-run/read/net/env) + unstable-API/auth caveats.
- arch-debt: advance cli-deploy-artifacts-missing (cloud target added; rollback/
  secrets + graph-complete guard + container artifacts remain).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(harness): record Deploy-S6 S3+S4 in run artifacts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(harness): record Deploy-S6 drift D-IMPL-3/D-IMPL-4 + S4 lint note

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(deploy-s6): replace embedded NUL byte with space in unstable-api-guard

Eval caveat B1: byte offset 3665 held a literal 0x00 that rendered as a
space, marking the whole safety-critical unstable-API guard file as
git-binary (Bin 0->4284, invisible to review/IMPL-EVAL) and a JSR/publish
landmine. Replaced 0x00 -> 0x20; file is now text and diffable. No
behavior change (dedupe key still separates api/source).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

* test(config): assert deno-deploy target retained in drop-behavior test

Rebase reconciliation: main's #364 drop-behavior test asserted the
{windows, linux} target set with `solaris` as the genuinely-unknown throwaway
key. Extend it for the deno-deploy member added by this branch — assert
`deno-deploy` is retained (org/app) alongside windows+linux and that `solaris`
is still dropped. Keeps the union honest post-rebase onto #363+#364.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

* test(deploy): include deno-deploy in default deploy-target registry test

Rebase reconciliation: `deploy-target-port_test.ts` pinned the default
`DeployTargetRegistry` to exactly the two bare-metal OS-service targets
(linux-service, windows-service). This branch registers the tier-1
`deno-deploy` cloud target into the SAME default registry (DEFAULT_DEPLOY_TARGETS
in deploy-target-registry.ts), so the sibling assertion regressed on CI
check-test (expected [linux-service, windows-service], actual
[deno-deploy, linux-service, windows-service]).

deno-deploy is a first-class marquee deploy target and legitimately belongs in
the default registry (the deno-deploy suite already asserts
DEFAULT_DEPLOY_TARGETS registers it). Update the test's expected set to the
localeCompare-sorted three keys, rename the test to reflect that it seeds the
OS-service targets plus deno-deploy, and assert the deno-deploy label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wKHquACkXnWPDgJYhhFjN

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:aspire area:cli area:deploy Deployment: CLI/Aspire deploy, targets, bare-metal epic:deployment Enterprise deployment framework epic priority:p1 High status:plan Harness plan phase type:feat wave:v1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Deploy-S7] Aspire Docker/Compose lane via TS AppHost

1 participant