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
24 changes: 16 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@

### Added

- CP-001 development package skeleton for the fresh-install rewrite, with no runtime dependencies.
- Truthful `actools version [--format human|json]`, controlled help delivery and bounded non-reflective exit-3 invocation errors; no installer or future command stubs are exposed.
- Narrow `Source CI` workflow and canonical source checker with exact workflow-shape enforcement, pinned action identities, hash-locked tooling input, complete scanner-coverage policy, closed wheel shape, installed-launcher/import-origin checks and reason-bound negative fixtures.
- Root license/notices, contributor/agent/security guidance and the initial package/source-CI ADR.
- CP-001 development package skeleton for the fresh-install rewrite and truthful `actools version`/help/error behavior.
- CP-001 narrow `Source CI` workflow and canonical fail-closed source checker with immutable action pins, locked tooling, complete scanner-coverage policy, closed wheel shape and installed-launcher checks.
- CP-002 configuration contract `1.0.0` for the `single-site-production` profile, with Draft 2020-12 schemas, strict UTF-8 JSON and restricted Actools YAML parsing, finite resource limits, explicit semantic checks and non-reflective errors.
- CP-002 omission-only canonical defaults with deterministic JSON-Pointer origin records using only `operator` and `release_default`.
- CP-002 RFC 8785 canonical bytes for resolved configuration and resolution envelopes, with six pinned Apache-2.0 JCS conformance-vector pairs and recorded provenance.

### Changed

- The Python distribution now declares exactly three runtime dependencies: `PyYAML==6.0.3`, `jsonschema==4.26.0`, and `rfc8785==0.1.4`.
- Source/package checks now expect the `actools.contracts` subpackage and its three packaged JSON contract resources, and installed-wheel verification uses a fresh isolated venv whose dependency closure is hash-installed from the actual generated `requirements/ci.lock` before the candidate wheel is installed with dependency resolution disabled; lock verification also fails closed unless the generated header records the exact accepted normalized compile command without `--no-index` and the frozen dependency/hash body is unchanged. The exact CP-001 CLI and unchanged Source CI workflow authority are preserved.
- CP-002 strict validation now rejects scoped/control-bearing endpoints, requires true end-of-input for owned identifiers/references, keeps endpoint port parsing total under extreme input, closes the reviewed YAML implicit-type lexical gaps, and enforces direct-mapping depth limits before recursive copying.

### Known limits

- This is a development skeleton, not a working Drupal installer or release.
- Source CI is configured by this candidate but has not run on GitHub before publication.
- The CP-001 lock must be regenerated/compared with the declared pip-tools/Python environment before remote publication because the coordinator build environment could not reach the package index.
- No CP-001 result qualifies servers, Drupal behavior, restore, signing, release or product-wide security gates.
- This remains a development package, not a working Drupal installer or production-qualified release.
- CP-002 introduces no CLI configuration command, wizard, filesystem publication, host discovery, journal, plan/apply operation, privileged execution, secret loading/generation or network/server effect.
- The historical r2 coding delivery omitted `requirements/ci.lock` by design. Every CP-002 review candidate must instead contain a resolver-generated lock and retained Human-Git receipts from the accepted Ubuntu Server 26.04.1 / CPython 3.14.7 / pip 26.2.1 / pip-tools 7.6.1 contract. A correction coding environment that cannot reproduce that environment must leave lock regeneration to Human-Git rather than fabricate or hand-edit it.
- JCS vector SHA-256 values in provenance require independent Human-Git receipt recomputation before the final candidate review.
- No CP-002 result by itself qualifies servers, Drupal behavior, restore, signing, release support or any product-wide gate.
14 changes: 7 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

This project is built as small, reviewed slices. Start with `AGENTS.md`, `coding/00_START_HERE_CODER_DOCUMENTATION.md`, the active architecture and the current task card. Use synthetic data only; do not place credentials or private diagnostics in source, issues, logs or prompts.

## CP-001 development environment
## Source-CI development environment

The reproducible source-CI target is **CPython 3.14.7 on Ubuntu 26.04 LTS x86_64**. Local E01 qualification uses Ubuntu Server 26.04.1 LTS; hosted source CI uses GitHub's `ubuntu-26.04` x64 runner label. This aligns source checks with architecture D01, but source CI alone does not qualify the installed host or full product stack.
The reproducible source-CI target is **CPython 3.14.7 on Ubuntu 26.04 LTS x86_64**. The accepted local reference environment is Ubuntu Server 26.04.1 LTS; hosted source CI uses GitHub's `ubuntu-26.04` x64 runner label. This aligns source checks with architecture D01, but source CI alone does not qualify the installed host or full product stack.

Create an isolated environment with CPython 3.14.7, then install the hash-locked source tools:
Create an isolated environment with CPython 3.14.7, then install the reviewed hash lock:

```text
python -m venv .venv
Expand All @@ -15,15 +15,15 @@ python -m pip install --require-hashes -r requirements/ci.lock
python tools/check_source.py
```

On Windows, activate the environment using its `Scripts` directory; the current CI lock is deliberately bound to the Ubuntu x86_64 runner, so use an equivalent Ubuntu/WSL environment for exact source-CI reproduction rather than weakening hashes.
On Windows, activate the environment using its `Scripts` directory; the final CI lock must be generated and qualified for the Ubuntu x86_64 source-test target, so use an equivalent Ubuntu/WSL environment for exact source-CI reproduction rather than weakening hashes.

Direct source inputs are in `requirements/ci.in`. The committed lock was generated from those exact bytes with CPython 3.14.7, pip 26.2.1 and `pip-tools==7.6.1` on the Ubuntu 26.04.1 x86_64 E01 host. Regenerate and compare under that contract before changing any pinned dependency. The lock header records the truthful generation command; the external E01 receipt binds the OS/interpreter/tool versions, input/output digests and semantic comparison.
Direct source inputs are in `requirements/ci.in`. CP-002 retains the five CP-001 source/test pins and adds exactly three runtime pins: `PyYAML==6.0.3`, `jsonschema==4.26.0`, and `rfc8785==0.1.4`. Generate `requirements/ci.lock` from those exact bytes only under the documented CPython 3.14.7 / Ubuntu Server 26.04.1 x86_64 contract with `pip==26.2.1` and `pip-tools==7.6.1`; do not hand-edit resolver hashes or reuse the CP-001 lock after changing direct inputs. See `docs/development/source-ci.md`.

## What the canonical check establishes

It verifies exact Python/tool versions and hash-closed inputs; the complete fixed source-workflow shape; unit and reason-bound controlled negative fixtures; a closed wheel inventory and metadata; the actual installed `actools` launcher plus import origin; truthful version/help and fixed non-reflective exit-3 invocation errors; real-pipe output failure; and exact complete `pip-audit==2.10.1` dependency coverage. Required execution that is unavailable, incomplete or errors remains a failed check.
It verifies exact Python/tool/runtime versions, `pip check`, and hash-closed inputs; the complete fixed source-workflow shape; strict configuration/parser/default/JCS tests; unit and reason-bound controlled negative fixtures; the closed wheel inventory and exact runtime metadata; the actual installed `actools` launcher plus import origin and packaged schema resource; truthful version/help and fixed non-reflective exit-3 invocation errors; real-pipe output failure; and exact complete `pip-audit==2.10.1` dependency coverage. Required execution that is unavailable, incomplete or errors remains a failed check.

A passing source check is not a release, server, Drupal, backup/restore or production qualification. Do not mark G01/G09/G22 or other product-wide gates PASS from CP-001 source fixtures.
A passing source check is not a release, server, Drupal, backup/restore or production qualification. CP-002 contract validity also does not mark G03/G09 or any other product-wide gate PASS.

## Review and integration

Expand Down
4 changes: 3 additions & 1 deletion NOTICE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Notices

This repository is the independent **actDrupal** installer project. Source added by CP-001 is licensed under the root MIT License and retains the Actools 2026 notice.
This repository is the independent **actDrupal** installer project. Actools-authored source is licensed under the root MIT License and retains the Actools 2026 notice.

Drupal, Open Source components installed later, operating-system packages, container images, and other third-party software retain their own licenses and notices. Their presence in a future installation does not relicense those components under this repository's MIT License.

CP-001 contains no imported runtime source from the historical `actoolsDrupal` repository. Any later third-party or inherited source must record its provenance and applicable license before integration.

CP-002 vendors only six compact JSON Canonicalization Scheme conformance input/output pairs from `cyberphone/json-canonicalization` commit `19d51d7fe467d4706a3ff08adf8a748f29fc21e0`. That upstream vector/reference material is Copyright 2018 Anders Rundgren and licensed under the Apache License, Version 2.0. Exact source paths, local byte digests and the applicable Apache-2.0 notice are recorded in `tests/fixtures/jcs/cyberphone/PROVENANCE.md`. No upstream implementation source is vendored by CP-002.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

Secure Drupal installation and operations toolkit being developed from the beginning in https://github.com/actools-pl/actDrupal.

**Status:** repository bootstrap only. The installer is not implemented or qualified. No installation command or production-ready release is available from this initial commit.
**Status:** pre-alpha development. CP-001 established the minimal Python package, truthful `actools version`/help behavior, and fail-closed source CI. The current unreleased CP-002 source adds a strict data-only configuration contract library; it does **not** add an installation command, wizard, host mutation, or production-ready release.

The current product scope is fresh installations only. Existing-site migration and legacy backup imports are excluded. Backup, restore, disaster recovery and supported updates for sites created by the new installer are planned requirements.
The current product scope is fresh installations only. Existing-site migration and legacy backup imports are excluded. Backup, restore, disaster recovery and supported updates for sites created by the new installer remain planned requirements.

Coding Package v1.3 and the active Architecture v1.5.1 are included under `coding/`. Start with the [coder documentation](coding/00_START_HERE_CODER_DOCUMENTATION.md). BOOT-001 imports and reviews this workflow; installer implementation remains pending. Product implementation begins with CP-001 only after the documentation import is reviewed, merged and its integration checks pass.
CP-002 configuration contract `1.0.0` supports only profile `single-site-production`. It parses strict UTF-8 JSON or the restricted Actools YAML subset, applies omission-only release defaults with explicit origins, validates the closed schema and semantic relationships, and exposes RFC 8785 canonical bytes. Contract-valid configuration is not installation or production readiness. See `docs/reference/configuration.md` and ADR-0002.

Coding Package v1.3 and the active Architecture v1.5.1 are included under `coding/`. Start with the [coder documentation](coding/00_START_HERE_CODER_DOCUMENTATION.md), the current task card, and the exact task base before changing source.
67 changes: 67 additions & 0 deletions docs/adr/0002-configuration-contract-and-canonicalization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# ADR-0002 — Strict configuration contract and RFC 8785 canonicalization

Status: **implemented in a local CP-002 candidate; CPD-12 correction/review, acceptance, merge and publication remain pending.**

## Context

CP-002 is the first WP02 configuration-contract slice after the accepted CP-001 package/source-CI baseline. Architecture v1.5.1 requires one canonical data model, strict schema ownership, omission/null/false fidelity, explicit default origins and identical data for later preview/authorization/apply consumers. This slice must remain a pure library: it adds no CLI command, wizard, host discovery, filesystem publication, journal, plan/apply operation, privileged execution, secret loading/generation or network/server effect.

The activation `CP002-ACT-32ecc89-v1` fixes configuration contract `1.0.0`, Draft 2020-12, profile `single-site-production`, RFC 8785 and runtime dependencies `PyYAML==6.0.3`, `jsonschema==4.26.0`, `rfc8785==0.1.4`.
The reviewed `rfc8785` tag `v0.1.4` resolves to upstream commit `4d9b161f6054301d98d0566e813d020fb019ee10`; the dependency is consumed as a pinned package, not vendored source.

## Decision

### One bounded configuration shape

The contract uses these closed groups:

- `schema_version`, `profile`;
- `installation.id`;
- `site.id`, `site.domain`;
- `environment.id`, `environment.type`;
- `platform.os_profile`, `platform.runtime_backend`;
- `capabilities.selected_ids` with only `valkey-cache` and `cloudflare-standard-proxy` in this version;
- `host.management_endpoint`, `host.filesystem_authority_id`, and the three accepted access-policy identifiers;
- `drupal.storage`, `drupal.cache.mode`, `drupal.ingress.mode`;
- `recovery.rpo_minutes`, `recovery.rto_minutes`;
- `monitoring` cadence plus `email`/`telegram` notification enable/reference records;
- `secrets.database_credentials` as a reference only;
- `references.policy`, `references.release`.

Every object is closed with `additionalProperties: false`. The schema expresses structure; `configuration.py` owns the finite cross-field checks: Valkey mode and capability must agree, standard Cloudflare ingress and capability must agree, an enabled notification requires a secret reference, and a disabled notification cannot retain one. These relationships assert configuration consistency only; they do not claim the capability is implemented or production-qualified.

### Strict parser boundary

JSON is bytes-first strict UTF-8 with duplicate-key detection before dictionary collapse, non-finite rejection, safe-integer bounds and a Unicode-scalar walk. Restricted YAML uses PyYAML only for syntax/tokens/events. Actools constructs the data model itself and rejects anchors, aliases, tags, merges, directives, multiple documents, duplicate/non-string keys, implicit empty nulls, YAML 1.1 boolean variants, dates/timestamps, non-finite values and YAML-only numeric forms. Quoted YAML remains string; only lowercase `null`/`true`/`false` and JSON-number lexical forms receive non-string types.

Resource limits are fixed at 1 MiB input, 32 container levels (root container is level 1), 256 entries/elements per mapping/sequence, 4,096 aggregate nodes, 16,384 Unicode scalar values per ordinary string and the I-JSON safe native integer range ±9,007,199,254,740,991. Schema `integer` fields use a strict native-integer type checker, so integral floats are not silently accepted as integers. Aggregate nodes count each container/scalar and every mapping-key scalar.

Errors expose only an owned JSON-pointer path plus a bounded reason code; raw parser failures fall back to `/` when an unowned key would otherwise be reflected, and wrapped parser/canonicalizer failures suppress underlying exception chains. Rejected values are never echoed.

### Format assertion

Draft 2020-12 validation uses an explicit `FormatChecker` whose registry is reduced to four Actools-owned formats: domain, endpoint, filesystem-authority ID and secret reference. Schema-quality validation fails if any other format name appears.

### Defaults and origins

JSON Schema `default` is not used for mutation. `configuration-defaults-1.0.0.json` is the sole release-default source. Defaults apply only where a field is omitted; explicit null/false/zero/empty values are preserved and may then fail the schema if invalid. The operator input is never modified in place.

Origins are a deterministic JSON-Pointer map for every resolved scalar leaf and every empty mapping/sequence leaf. Operator-present values receive `{"origin":"operator"}`. Release-default values additionally identify `configuration-defaults-1.0.0` and default-set version `1.0.0`. No `policy_default` source is invented.

### Canonical bytes and vectors

Canonical output is `rfc8785.dumps()` bytes for parser/validator-bounded I-JSON-compatible data, for both the resolved configuration and `{configuration, origins}` resolution envelope. Ordinary `json.dumps(sort_keys=True)` is not treated as canonicalization.

Six byte-for-byte published vectors are vendored from `cyberphone/json-canonicalization@19d51d7fe467d4706a3ff08adf8a748f29fc21e0`: arrays, french, structures, unicode, values and weird. Their Apache-2.0 provenance and byte receipts are recorded beside the fixtures. The upstream 100-million-number corpus is not vendored.

### Package/source-CI transition

The distribution still has version `0.1.0.dev0` and the CP-001 CLI remains untouched. The wheel grows from nine members to a closed sixteen-member shape: the two CP-001 Python files, four contract Python modules, three schema/default JSON resources and the same seven distribution metadata/license members. Runtime metadata must contain exactly the three accepted runtime pins. `.github/workflows/source-ci.yml` remains byte-for-byte the CP-001 workflow; the checker and lock inputs evolve underneath that unchanged authority.

## Consequences and evidence boundary

Configuration validity is not installation/production readiness. No host, Drupal, backup, restore, release-signing or product-wide gate is established by this ADR.

A CP-002 review candidate is complete only when `requirements/ci.lock` has been resolver-generated under the accepted Ubuntu Server 26.04.1 x86_64 / CPython 3.14.7 / pip 26.2.1 / pip-tools 7.6.1 contract and the corresponding local receipts are retained. The historical r2 coding delivery intentionally omitted the lock; Human-Git subsequently generated it for the reviewed local candidate. Any correction that changes the generated header must regenerate the lock in that exact environment rather than hand-editing it, while preserving the frozen dependency/hash body. Hosted Source CI remains unexecuted until publication is separately authorized.

The vector receipt values are present for deterministic source testing, but the packet-required Human-Git independent digest recomputation is still an evidence obligation before final review.
Loading