Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ body:
attributes:
label: Version or commit
description: Provide the package version, image tag, or commit SHA.
placeholder: 0.1.0
placeholder: 0.2.0
validations:
required: true

Expand Down
19 changes: 10 additions & 9 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ environment.
24, and 26. It also runs dependency review, dependency audit, full-history secret scanning and generates an
SPDX JSON source SBOM. Dependency review requires a public repository or the corresponding GitHub security
entitlement.
- `alpha-acceptance.yml` verifies the seven synthetic migration goldens and generates one representative Node,
Python, PHP and Go project. It installs each selected toolchain, verifies `monox.lock`, builds and tests the
workspaces, then starts the Node, Python and Laravel APIs and probes their health endpoints. A separate job
exercises the built-in local Cloudapter through doctor, deploy, an explicit health probe, status and
owned-service destroy. This is representative coverage, not the complete catalog matrix.
- `release-acceptance.yml` verifies the seven synthetic migration goldens and generates one representative
Node, Python, PHP and Go project. It installs each selected toolchain, verifies `monox.lock`, builds and
tests the workspaces, then starts the Node, Python and Laravel APIs and probes their health endpoints. A
separate job exercises the built-in local Cloudapter through doctor, deploy, an explicit health probe,
status and owned-service destroy. This is representative coverage, not the complete catalog matrix.
- `catalog-matrix.yml` is scheduled weekly and can be started manually. It generates every one of the 24
bundled workspace recipes in isolation, installs the selected toolchain, verifies the lock, runs tests and
builds. It then runs the shared acceptance helper, which probes services, checks workers, waits for jobs and
Expand All @@ -52,10 +52,11 @@ environment.
continue to block publication.

`create-monox` exists on npm under the `mosharush` maintainer account. Version 0.1.0 was the first release
from this public repository and upgraded the historical 0.0.5 package in place. The public `latest` tag is
currently 0.1.2; the 0.2 source stays on an alpha prerelease until the release gates are complete. Releases
keep the `https://github.com/Mosharush/MonoX` metadata, include the MIT license in the tarball, and use
trusted publishing with registry provenance.
from this public repository and upgraded the historical 0.0.5 package in place. Stable releases publish under
`latest`; prereleases publish under `next`. Verification waits for registry propagation, checks the expected
dist-tag, signed provenance and exact Git commit, then runs a clean-cache consumer. Releases keep the
`https://github.com/Mosharush/MonoX` metadata, include the MIT license in the tarball, and use trusted
publishing without a long-lived npm token.

CodeQL uses GitHub default setup with JavaScript and TypeScript analysis. Keep that repository-level setup
instead of adding a duplicate advanced workflow.
Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/npm-release-verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ jobs:
PACKAGE_VERSION: ${{ steps.release.outputs.package_version }}
RELEASE_TAG: ${{ inputs.release_tag }}
SOURCE_SHA: ${{ steps.release.outputs.source_sha }}
VERIFY_DIST_TAG: ${{ github.event_name != 'workflow_dispatch' }}
run: |
set -euo pipefail

Expand Down Expand Up @@ -145,6 +146,43 @@ jobs:
sleep 10
done

if [[ "${VERIFY_DIST_TAG}" == "true" ]]; then
if [[ "${PACKAGE_VERSION}" == *-* ]]; then
expected_dist_tag="next"
else
expected_dist_tag="latest"
fi
for attempt in {1..18}; do
tag_cache="$(mktemp -d)"
tag_record="$(
NPM_CONFIG_CACHE="${tag_cache}" \
npx --yes "npm@${NPM_CLI_VERSION}" view \
create-monox dist-tags \
--json \
--workspaces=false 2>/dev/null || true
)"
if DIST_TAG_RECORD="${tag_record}" \
EXPECTED_DIST_TAG="${expected_dist_tag}" \
PACKAGE_VERSION="${PACKAGE_VERSION}" \
node --input-type=module -e "
try {
const raw = JSON.parse(process.env.DIST_TAG_RECORD);
const tags = Array.isArray(raw) ? raw[0] : raw;
process.exit(tags?.[process.env.EXPECTED_DIST_TAG] === process.env.PACKAGE_VERSION ? 0 : 1);
} catch {
process.exit(1);
}
"; then
break
fi
if [[ "${attempt}" -eq 18 ]]; then
echo "npm dist-tag ${expected_dist_tag} does not point to ${PACKAGE_VERSION}." >&2
exit 1
fi
sleep 10
done
fi

package_integrity="$(
REGISTRY_RECORD="${registry_record}" node --input-type=module -e \
"const raw = JSON.parse(process.env.REGISTRY_RECORD); const data = Array.isArray(raw) ? raw[0] : raw; process.stdout.write(data?.['dist.integrity'] ?? data?.dist?.integrity ?? '')"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 0.2 alpha acceptance
name: 0.2 release acceptance

on:
push:
Expand All @@ -11,7 +11,7 @@ permissions:
contents: read

concurrency:
group: alpha-acceptance-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: release-acceptance-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
Expand Down
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes will be documented here.

## Unreleased

## 0.2.0 - 2026-07-26

Version 0.2.0 stabilizes deterministic project generation, package-owned deployment contracts and the
source-tested offline planning and rendering surface. Remote infrastructure execution is not promoted to
stable support: PM2, SSH, Coolify and Kubernetes remain guarded behind injected transports, while AWS and
Google Cloud providers remain plan-only.

### Added

- Package-owned deployment contract v2 with strict JSON Schema, generated TypeScript declarations and a
Expand Down Expand Up @@ -41,8 +48,8 @@ All notable changes will be documented here.
`applications[]` list.
- Replaced legacy zero-maximum-replica parking with explicit `suspended: true`.
- Replaced side deployments with deterministic variants and provider fields with target bindings.
- Bumped source and `create-monox` metadata to `0.2.0-alpha.1`. A prerelease tag and npm publish remain gated
by the complete acceptance suite and security prerequisites.
- Promoted the deterministic generator and offline contracts to `0.2.0`, published through the protected npm
workflow under `latest` only when the exact release tag and source commit match.
- Aligned Nuxt 4 with its project-reference TypeScript layout and Angular 22 with the current `@angular/build`
builder.
- Namespaced generated Python distributions and modules so workspace names such as `fastapi` cannot shadow a
Expand All @@ -64,7 +71,9 @@ All notable changes will be documented here.

### Known limitations

- AWS and Google Cloud packages are plan-only in this alpha and do not invoke Pulumi Automation API.
- `create-monox@0.2.0` does not install the source-tree `@monox/cli`; generated projects receive deployment
contracts and fail-closed placeholders, while the delivery CLI remains npm-private.
- AWS and Google Cloud packages are plan-only in 0.2.0 and do not invoke Pulumi Automation API.
- PM2, SSH, Coolify and Kubernetes adapters have not completed their live acceptance matrices.
- Kubernetes add-on chart coordinates and digests remain intentionally unverified and non-executable.
- The private production reference has not completed a MonoX 0.2 canary and proven rollback, so it is not yet
Expand Down
52 changes: 29 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@ Every deployable package owns a versioned `package.json.deployment` block. The r
project boundaries, workload profiles, environments, targets and add-ons. There is no second application list
to keep in sync.

> Status: `0.2.0-alpha.1` is a source prerelease. The protected npm workflow publishes prereleases under the
> `next` dist-tag only after its release gate passes. The stable npm line remains available through `latest`.
> `create-monox` 0.2.0 is the stable generator release and is published through the `latest` dist-tag. Stable
> support covers deterministic project generation and the source-tested offline contracts described below.
> Remote infrastructure execution remains guarded, acceptance-pending or plan-only as marked in the
> [capability status](docs/capability-status.md).

[Project site](https://monox.dev) | [Architecture](docs/architecture.md) |
[Deployment contract](docs/deployment.md) | [create-monox on npm](https://www.npmjs.com/package/create-monox)
| [Security gate](docs/security-gate.md)

## Generate a product

After the alpha is published under `next`:
Create a project from the stable channel:

```bash
npm create monox@next -- my-product \
npm create monox@latest -- my-product \
--workspace api=node-fastify-api \
--workspace web=react-vite-web \
--workspace jobs=node-worker \
Expand Down Expand Up @@ -120,21 +122,25 @@ immutable. Every resolved base workload and variant must match exactly one targe

See [Deployment contract](docs/deployment.md) for the complete resolution order and safety rules.

## CLI
## Source-tree delivery CLI

The delivery CLI below is tested from this repository with `yarn monox`. It is not installed by
`create-monox@0.2.0`; generated projects receive the deployment contracts and fail-closed placeholders only.
`@monox/cli` remains npm-private until its package scope and independent consumer contract are ready.

```text
monox validate
monox config explain <package> --env <environment> [--target <target>]
monox doctor --env <environment> [--target <target>]
monox plan --env <environment> --all|--select <ids>|--affected
monox render --env <environment> --target <target> --all|--select <ids>|--affected --output-dir <dir>
monox deploy --env <environment> --all|--select <ids>|--affected
monox apply --plan <file>
monox status --env <environment> --target <target>
monox rollback --env <environment> --target <target> --revision <revision>
monox destroy --env <environment> --target <target> --confirm <project/environment/target>
monox cloud plan|setup|status|destroy --env <environment> --target <target>
monox migrate deployment --from monox-v1|legacy-production --input <file>
yarn monox validate
yarn monox config explain <package> --env <environment> [--target <target>]
yarn monox doctor --env <environment> [--target <target>]
yarn monox plan --env <environment> --all|--select <ids>|--affected
yarn monox render --env <environment> --target <target> --all|--select <ids>|--affected --output-dir <dir>
yarn monox deploy --env <environment> --all|--select <ids>|--affected
yarn monox apply --plan <file>
yarn monox status --env <environment> --target <target>
yarn monox rollback --env <environment> --target <target> --revision <revision>
yarn monox destroy --env <environment> --target <target> --confirm <project/environment/target>
yarn monox cloud plan|setup|status|destroy --env <environment> --target <target>
yarn monox migrate deployment --from monox-v1|legacy-production --input <file>
```

An environment and one workload selector are mandatory for workload state changes. Production state changes
Expand All @@ -143,7 +149,7 @@ require `CI=true`, a protected environment and an identity reference. Destroy re

## Maintained catalog

The alpha catalog contains 24 workspace recipes:
The stable generator contains 24 bundled workspace recipes:

- JavaScript and TypeScript: Node HTTP, Fastify, Express, Nest, Hono, workers, cron, React, Vue, Next, Nuxt,
SvelteKit, Angular and TypeScript libraries.
Expand All @@ -154,8 +160,8 @@ The alpha catalog contains 24 workspace recipes:
Java, .NET and Rust remain extension recipes until they have maintained install, test, build and runtime CI.
Yarn, pnpm and npm are supported for JavaScript workspaces.

A scheduled 24-recipe matrix installs, tests, builds and starts or probes every built-in workspace. The first
hosted matrix run remains part of the prerelease evidence gate.
A scheduled 24-recipe matrix installs, tests, builds and starts or probes every built-in workspace. Release
candidates rerun that hosted matrix against the exact candidate commit.

The 28 add-on recipes cover data, messaging, AI, search, storage, identity, development, observability and
Kubernetes platform components. LocalStack and Mailpit are rejected for production. Stateful Kubernetes
Expand All @@ -171,7 +177,7 @@ methods are versioned through `Cloudapter`: `doctor`, `validate`, `plan`, `rende
Local Docker Compose has a built-in executor that runs only allowlisted `docker compose` argument arrays with
`shell: false`, bounded readiness checks and explicit owned services. PM2, SSH, Coolify and Kubernetes retain
explicitly injected transports, so the CLI does not infer a host, credential or cluster context. AWS and GCP
are plan-only in this alpha; provider executors and live sandbox apply remain release gates.
are plan-only in 0.2.0; provider executors and live sandbox apply are not part of the stable support contract.

## Work on MonoX

Expand All @@ -195,8 +201,8 @@ docker compose --env-file infra/local/.env -f infra/local/docker-compose.yml --p
`yarn check` covers formatting, repository boundaries, deployment resolution, tests, builds and infrastructure
validation. MonoX repository CI repeats the gate on Node.js 22, 24 and 26, tests Yarn, npm and pnpm consumers,
audits dependencies, scans the full history and creates an SPDX JSON source SBOM. Generated project CI is
limited to immutable install, lock verification, tests and builds. Alpha acceptance also runs a generated
local Docker target through doctor, deploy, an explicit health probe, status and owned-only destroy.
limited to immutable install, lock verification, tests and builds. The 0.2 acceptance workflow also runs a
generated local Docker target through doctor, deploy, an explicit health probe, status and owned-only destroy.

## Clean-room boundary

Expand Down
3 changes: 2 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## Supported versions

MonoX is pre-release software. Security fixes target the latest `0.x` release and the default branch.
Security fixes target the current `0.2.x` release line and the default branch. Earlier `0.x` releases may
receive fixes when a safe backport is practical.

## Report a vulnerability

Expand Down
3 changes: 2 additions & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ Use GitHub Issues for reproducible bugs, scoped feature requests, design questio
Discussions can become the long-form support channel after the public repository enables it. Security reports
follow [SECURITY.md](SECURITY.md).

MonoX is pre-release software. There is no production support SLA.
MonoX 0.2 has a stable generator and offline-contract support boundary. There is no production support SLA,
and remote adapters keep the acceptance status documented in the repository.
2 changes: 1 addition & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@monox/api",
"version": "0.2.0-alpha.1",
"version": "0.2.0",
"private": true,
"type": "module",
"deployment": {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const securityHeaders = {
export function createApiServer(options = {}) {
const environment = normalizeEnvironment(options.environment ?? process.env.MONOX_ENV ?? 'local');
const startedAt = Date.now();
const runtime = options.runtime ?? createAppRuntime({ name: '@monox/api', version: '0.2.0-alpha.1' });
const runtime = options.runtime ?? createAppRuntime({ name: '@monox/api', version: '0.2.0' });

const server = createServer((request, response) => {
const requestStartedAt = process.hrtime.bigint();
Expand Down
2 changes: 1 addition & 1 deletion apps/api/test/server.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ test('serves health and synthetic API responses', async () => {
assert.equal(health.status, 200);
assert.deepEqual(await health.json(), {
name: '@monox/api',
version: '0.2.0-alpha.1',
version: '0.2.0',
ready: true,
live: true,
state: 'running',
Expand Down
2 changes: 1 addition & 1 deletion apps/web/deploy/nginx/monox.dev.conf
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ server {
error_log /home/monox/logs/nginx/error.log;

add_header Content-Language $monox_content_language always;
add_header Content-Security-Policy "default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; form-action 'none'; script-src 'sha256-yobifisrUX5jmFbF2OJOXGbUsGsYDPdPdkH4ehe2Ll0='; style-src 'self'; img-src 'self' data:" always;
add_header Content-Security-Policy "default-src 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none'; form-action 'none'; script-src 'sha256-j5+huJAo2bEyExTIsvCL8uNR05Fe+DupuuQrek0PIb4='; style-src 'self'; img-src 'self' data:" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Permissions-Policy "camera=(), geolocation=(), microphone=(), payment=(), usb=()" always;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@monox/web",
"version": "0.2.0-alpha.1",
"version": "0.2.0",
"private": true,
"type": "module",
"deployment": {
Expand Down
Loading
Loading