Prepare Conductor v1.0.0 release

This commit is contained in:
Victor Wiebe 2026-08-08 14:21:40 -04:00
parent ade2b10033
commit 0c84691528
35 changed files with 916 additions and 297 deletions

View File

@ -4,8 +4,8 @@ CONDUCTOR_SECRET_KEY=replace-with-64-hex-characters
CONDUCTOR_SESSION_KEY=replace-with-an-independent-random-value-at-least-32-bytes
CONDUCTOR_IMAGE=gitea.skeletonworks.online/vwiebe/conductor
CONDUCTOR_VERSION=v0.1.0
CONDUCTOR_BIND_ADDRESS=0.0.0.0
CONDUCTOR_VERSION=v1.0.0
CONDUCTOR_BIND_ADDRESS=127.0.0.1
CONDUCTOR_PORT=8080
CONDUCTOR_MEM_LIMIT=1g
CONDUCTOR_CPUS=1.5

View File

@ -4,7 +4,6 @@ on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
jobs:
production-image:
@ -39,7 +38,7 @@ jobs:
with:
context: .
file: Dockerfile.production
platforms: linux/amd64,linux/arm64
platforms: linux/amd64
push: true
build-args: |
VERSION=${{ steps.metadata.outputs.version }}

View File

@ -352,6 +352,6 @@ The final manual continuation passed Test 6A and Test 6B; the user confirmed all
- Docker restart preserved a disposable demo project; cleanup deleted it and cleared history. Standard Compose was restored with backend health, frontend HTTP 200, empty executions/secrets, and empty secret/internal-origin configuration.
- Tracked-source credential-pattern scan found no private-key or common token signatures. Backend production dependency audit reports zero vulnerabilities after non-breaking lockfile fixes.
- Frontend Create React App transitive build/development advisories remain a documented Slice 8 packaging/toolchain risk.
- Remaining gate: proportional manual acceptance in `SLICE6_MANUAL_TEST.md`, final cleanup evidence, and explicit user sign-off.
- Remaining gate at that point: the Slice 6 proportional manual procedure, final cleanup evidence, and explicit user sign-off.
The user granted explicit final Slice 5 sign-off on 2026-08-04 with the wording: “Confirm slice5 signoff.” Slice 5 is complete.

View File

@ -44,6 +44,11 @@ The `docs/` copies of requirements, architecture, and future-idea specifications
## Current Implementation State
### Release identity
- The first production application release is `v1.0.0`.
- The canonical project-document schema remains `0.1.0`; application and schema versions are independent compatibility contracts.
### Foundation
- React and TypeScript frontend
@ -325,9 +330,16 @@ Date: 2026-07-20
- Backend production dependencies audit clean. Create React App retains high transitive build/development advisories with no supported non-breaking fix; record this as a Slice 8 packaging/toolchain release risk.
- Standard Compose is restored healthy with empty history/secrets/configuration after automated cleanup. No commit or push occurred.
- On 2026-08-07, the user reported all six manual workflows pass. Stored-history and backend-log marker scans passed, the expected redaction and `SECRET_NOT_FOUND` evidence was present, and cleanup restored healthy standard Compose with empty executions, secrets, secret-key configuration, and internal-origin configuration.
- The Actions & Bindings information-density feedback is tracked in `SLICE6a.md` as a separate UX follow-up. The user granted explicit final Slice 6 sign-off on 2026-08-07 with the exact wording: “I grant explicit final Slice 6 sign-off.” Slice 6 is complete.
- Slice 6a implementation and automation are complete through the manual gate: accessible collapsible sections/cards, compact record summaries, grouped REST editing, explicit secret creation, visible collapsed issue counts, and mounted-state preservation are implemented. Focused coverage passes at 18 tests; full frontend coverage passes at 25 suites / 520 tests; TypeScript and production build pass. `Slice 6a Density Manual` (`#22`) is prepared for `SLICE6a_MANUAL_TEST.md`.
- The Actions & Bindings information-density feedback was addressed as a separate Slice 6a UX follow-up. The user granted explicit final Slice 6 sign-off on 2026-08-07 with the exact wording: “I grant explicit final Slice 6 sign-off.” Slice 6 is complete.
- Slice 6a implementation and automation are complete through the manual gate: accessible collapsible sections/cards, compact record summaries, grouped REST editing, explicit secret creation, visible collapsed issue counts, and mounted-state preservation are implemented. Focused coverage passes at 18 tests; full frontend coverage passes at 25 suites / 520 tests; TypeScript and production build pass. `Slice 6a Density Manual` (`#22`) was prepared for the local Slice 6a manual procedure.
- The user reported all Slice 6a manual UX tests pass and that the changes look good. Disposable project `#22` was deleted; backend health, frontend HTTP 200, empty secrets, and empty history pass.
- The user granted explicit final Slice 6a sign-off on 2026-08-07 with the exact wording: “I grant explicit final Slice 6a sign-off.” Slice 6a is complete.
- Slice 7 governance reconciliation completed on 2026-08-07. README, approved scope, roadmap, requirements, and architecture now consistently exclude AI and advanced capabilities from v0.1.0, reflect implemented canonical/proxy/secret/auth/history/validation behavior, and contain no material open release questions. `docs/MVP_TRACEABILITY.md` maps R1R14 and all six accepted workflows to slices/evidence. The new `npm run test:governance` regression check passes. Slice 7 required no new manual gate because its product-owner scope decision was already approved.
- The product owner added Slice 7a local authentication/RBAC and immutable standalone publishing to the v0.1 boundary before Slice 8. Agreed defaults: global admin/user roles, admin-only authoring/user/publishing management, public versus authenticated snapshots, admin access to all apps, all authenticated users access to restricted apps, public anonymous-action-only enforcement, and server-owned published execution. Slice 7a establishes provider-neutral auth architecture; post-v0.1 Slice 9 adds OIDC/SSO. Traceability and governance checks now cover R1R16.
### 2026-08-08 v1.0.0 Production Release Preparation Addendum
- The product owner promoted the completed MVP feature set to the first production application release, `v1.0.0`.
- The canonical project-document schema remains `0.1.0`; no stored-project or publication-snapshot migration is part of the application-version promotion.
- Release-facing documentation, package metadata, Compose/environment defaults, Linux/AMD64 publication settings, and the SkeletonWorks default image were aligned to `v1.0.0`.
- The `v1.0.0` source tag, container image, Gitea Release entry, artifact digests/checksums, and final external/manual acceptance remain pending and must not be reported as complete before publication.

View File

@ -2,7 +2,7 @@
## Status
Approved on 2026-07-18. All six workflows passed Slice 6 release validation and received explicit product-owner sign-off on 2026-08-07.
Approved on 2026-07-18. All six workflows passed Slice 6 release validation and received explicit product-owner sign-off on 2026-08-07. On 2026-08-08, the product owner adopted this accepted MVP scope unchanged as the Conductor v1.0.0 production-release boundary.
## AI Decision
@ -72,13 +72,13 @@ These are end-to-end acceptance scenarios. They demonstrate that Conductor can b
Approved on 2026-08-07 for Slice 7a:
- Local username/password authentication with global `admin` and `user` roles is required before v0.1.0 packaging.
- Local username/password authentication with global `admin` and `user` roles is required for the v1.0.0 release.
- Admins alone may author projects, manage users/secrets, and publish applications.
- Publishing creates an immutable validated snapshot under a standalone application URL without editor controls.
- Published visibility is either public or restricted to all authenticated users; admins can access every active published application.
- Public snapshots may contain only anonymous REST actions. Authenticated snapshots may use server-resolved credential-backed actions.
- Published action execution must resolve the server-owned snapshot and must not accept browser-substituted URLs, action definitions, authentication modes, or secret references.
- Authentication and authorization architecture must remain provider-neutral so post-v0.1.0 OIDC/SSO can reuse the same users, roles, sessions, capabilities, and publication rules.
- Authentication and authorization architecture must remain provider-neutral so post-MVP OIDC/SSO can reuse the same users, roles, sessions, capabilities, and publication rules.
- Per-application assignments, custom roles, groups, and OIDC/SSO are not part of Slice 7a.
## Release Boundary

View File

@ -79,20 +79,15 @@ docker compose up --build
Conductor's production distribution is one non-root container serving the compiled frontend, published application routes, and backend API on port 8080. SQLite data is stored in a persistent volume. The development stack above remains separate.
The command below is the final production coordinate and will succeed only after the public `v1.0.0` Gitea Release and container image have been published. Until then, a missing-manifest response means publication is incomplete; do not substitute `latest` or private registry credentials.
```bash
curl -O https://gitea.skeletonworks.online/vwiebe/conductor/raw/tag/v0.1.0/compose.production.yml
curl -o .env https://gitea.skeletonworks.online/vwiebe/conductor/raw/tag/v0.1.0/.env.production.example
# Replace both placeholder keys with independent values from:
openssl rand -hex 32
docker compose --env-file .env -f compose.production.yml pull
docker compose --env-file .env -f compose.production.yml up -d
docker pull gitea.skeletonworks.online/vwiebe/conductor:v1.0.0
```
Open `http://localhost:8080` and create the first administrator in the browser. There are no default credentials.
The v1.0.0 production image supports Linux/AMD64. Anonymous source and image availability are mandatory publication checks. A complete internet-facing installation also requires persistent generated keys, the tagged Compose bundle, a data volume, and HTTPS.
For source builds, reverse proxies, upgrades, backups, restores, and SkeletonWorks installation, see [docs/INSTALL.md](docs/INSTALL.md) and [docs/OPERATIONS.md](docs/OPERATIONS.md).
Independent self-hosters should follow [docs/INSTALL.md](docs/INSTALL.md) from start to finish. For backup, restore, upgrade, and rollback, see [docs/OPERATIONS.md](docs/OPERATIONS.md). Conductor never ships a default username or password.
---
@ -100,21 +95,27 @@ For source builds, reverse proxies, upgrades, backups, restores, and SkeletonWor
| Document | Description |
|---|---|
| [ROADMAP.md](ROADMAP.md) | Unified v0.1.0 work plan grouped by function and slice |
| [MVP_SCOPE.md](MVP_SCOPE.md) | Approved v0.1.0 release boundary and acceptance workflows |
| [ROADMAP.md](ROADMAP.md) | Unified v1.0.0 work plan grouped by function and slice |
| [MVP_SCOPE.md](MVP_SCOPE.md) | Approved MVP and v1.0.0 release boundary |
| [TESTING.md](TESTING.md) | Detailed manual test workflows and acceptance records |
| [docs/REQUIREMENTS.md](docs/REQUIREMENTS.md) | Full product requirements |
| [docs/MVP_TRACEABILITY.md](docs/MVP_TRACEABILITY.md) | v0.1.0 requirements mapped to slices and validation evidence |
| [docs/MVP_TRACEABILITY.md](docs/MVP_TRACEABILITY.md) | v1.0.0 requirements mapped to slices and validation evidence |
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Technical architecture |
| [docs/NICE-TO-HAVE.md](docs/NICE-TO-HAVE.md) | Future enhancements |
| [docs/BUILD_AND_TEST_PLAN.md](docs/BUILD_AND_TEST_PLAN.md) | Incremental build and test plan |
| [docs/INSTALL.md](docs/INSTALL.md) | Public source/container and reverse-proxy installation |
| [docs/OPERATIONS.md](docs/OPERATIONS.md) | Production configuration, backup, restore, upgrade, and rollback |
| [docs/RELEASE.md](docs/RELEASE.md) | Image tagging, release construction, and publication |
| [docs/USER_GUIDE.md](docs/USER_GUIDE.md) | Admin/user authoring, runtime, and publishing workflows |
| [docs/RELEASE_NOTES_v1.0.0.md](docs/RELEASE_NOTES_v1.0.0.md) | v1.0.0 capabilities, compatibility, and publication record requirements |
| [docs/USER_GUIDE.md](docs/USER_GUIDE.md) | Project authoring and published-application use |
| [docs/ADMIN_GUIDE.md](docs/ADMIN_GUIDE.md) | Users, sessions, credentials, publishing, and execution history |
| [docs/FIRST_RUN_SETUP.md](docs/FIRST_RUN_SETUP.md) | First-administrator setup and recovery entry points |
| [docs/SECRETS.md](docs/SECRETS.md) | Credential encryption and key lifecycle |
| [docs/PROXY_SECURITY.md](docs/PROXY_SECURITY.md) | REST destination, request, response, and history policy |
| [docs/AUTHORIZATION_AND_PUBLISHING_SECURITY.md](docs/AUTHORIZATION_AND_PUBLISHING_SECURITY.md) | Authentication, RBAC, and publication trust boundaries |
| [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md) | Architecture, invariants, tests, and contribution workflow |
| [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | Production and application troubleshooting |
| [docs/KNOWN_LIMITATIONS.md](docs/KNOWN_LIMITATIONS.md) | Explicit v0.1.0 limitations and deferred capabilities |
| [docs/KNOWN_LIMITATIONS.md](docs/KNOWN_LIMITATIONS.md) | Explicit v1.0.0 limitations and deferred capabilities |
---

View File

@ -1,17 +1,17 @@
# Conductor Unified Roadmap to v0.1.0
# Conductor Unified Roadmap to v1.0.0
## Purpose
This is the master index of completed and remaining work for Conductor v0.1.0. It supersedes the older numbered-step roadmap and legacy task inventory while reconciling `MVP_SCOPE.md` and `SLICE1.md` through `SLICE8.md`.
This is the master index of completed and remaining work for Conductor v1.0.0. The accepted MVP originally used `v0.1.0` as its planning label; on 2026-08-08, the product owner promoted that completed scope unchanged to the first production release, `v1.0.0`. This roadmap supersedes the older numbered-step roadmap and legacy task inventory while reconciling `MVP_SCOPE.md` and `SLICE1.md` through `SLICE8.md`.
The slice files remain the detailed implementation plans. When an older list conflicts with the approved MVP boundary or current acceptance evidence, this document follows `MVP_SCOPE.md`, the slice files, and recorded manual acceptance in that order.
The slice files are historical implementation snapshots. Current completion and release status is authoritative in this roadmap, `MVP_SCOPE.md`, `TESTING.md`, and the release documentation.
## Status Legend
- [x] Implemented and accepted, or a completed product decision.
- [ ] Remaining v0.1.0 work.
- [ ] Remaining v1.0.0 work.
- **Partial** means useful work has passed, but the slice-level release gate is not complete.
- **Post-MVP** means deliberately excluded from v0.1.0.
- **Post-MVP** means deliberately excluded from v1.0.0.
## Slice Summary
@ -23,14 +23,14 @@ The slice files remain the detailed implementation plans. When an older list con
| [Slice 4](SLICE4.md) | Proxy security and observability | Complete | None |
| [Slice 5](SLICE5.md) | Validation and error handling | Complete | None |
| [Slice 6](SLICE6.md) | Testing and release validation | Complete | None |
| [Slice 6a](SLICE6a.md) | Editor information density and progressive disclosure | Complete | None |
| Slice 6a | Editor information density and progressive disclosure | Complete | None |
| [Slice 7](SLICE7.md) | MVP scope decision and requirement governance | Complete | None |
| [Slice 7a](SLICE7a.md) | Local authentication, RBAC, and application publishing | Complete | Implementation, security validation, manual acceptance, cleanup, and explicit sign-off passed |
| [Slice 7b](SLICE7b.md) | Browser-based first-run administrator setup | Complete | Fresh-install setup, takeover prevention, recovery validation, manual acceptance, and explicit sign-off passed |
| [Slice 7c](SLICE7c.md) | Multi-page applications and variable scope | Complete | Page authoring, scoped runtime, deep links, security validation, and explicit sign-off |
| [Slice 7d](SLICE7d.md) | Visual Editor professional command ribbon | Complete | None |
| [Slice 8](SLICE8.md) | Documentation and release packaging | Partial | Unified roadmap complete; broader documentation ownership, reconciliation, guides, and release packaging remain |
| [Slice 9](SLICE9.md) | OIDC and enterprise SSO | Post-MVP | Begins after Slice 7a; provider and provisioning decisions remain |
| Slice 7a | Local authentication, RBAC, and application publishing | Complete | Implementation, security validation, manual acceptance, cleanup, and explicit sign-off passed |
| Slice 7b | Browser-based first-run administrator setup | Complete | Fresh-install setup, takeover prevention, recovery validation, manual acceptance, and explicit sign-off passed |
| Slice 7c | Multi-page applications and variable scope | Complete | Page authoring, scoped runtime, deep links, security validation, and explicit sign-off |
| Slice 7d | Visual Editor professional command ribbon | Complete | None |
| [Slice 8](SLICE8.md) | Documentation and release packaging | Partial | Documentation and local validation complete; v1.0.0 artifact publication and external/manual acceptance remain |
| Slice 9 | OIDC and enterprise SSO | Post-MVP | Begins after Slice 7a; provider and provisioning decisions remain |
## 1. MVP GUI Components
@ -53,7 +53,7 @@ The slice files remain the detailed implementation plans. When an older list con
- [ ] Add reusable themes and component libraries.
- [ ] Add editable Table cells, sorting, filtering, pagination, CSV import/export, row actions, and multi-selection.
Table pagination requires a separate client-side versus server-side design discussion and is not a v0.1.0 release requirement.
Table pagination requires a separate client-side versus server-side design discussion and is not a v1.0.0 release requirement.
## 2. Visual Configuration Workflows
@ -77,7 +77,7 @@ These items replace the older roadmap's pending Steps 19 and 20. They are not ne
- [x] Run and record the final workflow-launcher acceptance without hand-editing JSON.
- [x] Run and record the final dependent-data acceptance, including initial Dropdown population.
- [x] Mark the five Slice 2 acceptance criteria complete after those workflows pass.
- [x] Retain and document the fixed 30-second backend request timeout for v0.1.0; defer a bounded canonical per-action timeout to proxy-policy work.
- [x] Retain and document the fixed 30-second backend request timeout for the initial production release; defer a bounded canonical per-action timeout to proxy-policy work.
- [x] Correct action and response-binding diagnostics so page `onLoad` counts as a valid trigger and the UI uses clear component-or-page-event wording.
- [x] Manually confirm the corrected Actions & Bindings view no longer reports false untriggered-action or binding warnings for page `onLoad`.
- [x] Manually accept the implemented Actions & Bindings information-architecture improvements for clearer action, binding, and variable cards, hierarchy, spacing, and summaries.
@ -162,7 +162,7 @@ Enterprise SIEM integration, RBAC, and enterprise audit retention remain post-MV
- [x] Centralize backend schema validation and use it at every persistence boundary.
- [x] Reject invalid projects without partial database updates.
- [x] Add supported schema-version and compatibility behavior.
- [x] Decide how invalid stored JSON is handled and whether v0.1.0 needs migrations.
- [x] Decide how invalid stored JSON is handled and whether the initial release needs migrations.
- [x] Verify explicit `null`, missing values, empty arrays, and empty objects round-trip correctly.
- [x] Confirm backend default projects are canonical and schema-valid.
@ -181,7 +181,7 @@ Enterprise SIEM integration, RBAC, and enterprise audit retention remain post-MV
- [x] Prevent new uses of deprecated `action.responseMapping`, inert `ComponentEvent.inputMap`, and unused component-level binding shapes.
- [x] Resolve, remove, document, or explicitly defer every modeled-but-unexecuted field, including `Binding.transform`.
- [x] Strengthen `project.settings` TypeScript typing to match the schema.
- [x] Decide whether backend-supported project deletion requires a v0.1.0 UI control.
- [x] Decide whether backend-supported project deletion requires an initial-release UI control.
- [x] Review deletion confirmations, keyboard accessibility, component disabled/hidden behavior, and Inspector/runtime diagnostic agreement.
- [x] Add malformed, semantic, version, rollback, and recovery regression tests.
@ -225,23 +225,23 @@ Enterprise SIEM integration, RBAC, and enterprise audit retention remain post-MV
- [x] Confirm through automated regression and credential-pattern scan that runtime state is never persisted and the repository contains no credentials or generated data.
- [x] Record commands, counts, artifacts, limitations, defects, and accepted risks.
- [x] Confirm no unresolved critical or high-severity defects remain.
- [x] Pass the published final acceptance checklist in `SLICE6_MANUAL_TEST.md`.
- [x] Pass the final manual acceptance recorded in `TESTING.md`.
Controlled orchestration is not required in the v0.1.0 demonstration. Execution history is included only if Slice 4 retains it as a release requirement.
Controlled orchestration is not required in the v1.0.0 demonstration. Execution history is included only if Slice 4 retains it as a release requirement.
## 7. MVP Scope and Requirement Governance
### Slice 7 — Completed decisions
- [x] Exclude IBM Bob, watsonx, and other AI dependencies from v0.1.0.
- [x] Require all five modeled authentication modes for v0.1.0.
- [x] Exclude IBM Bob, watsonx, and other AI dependencies from v1.0.0.
- [x] Require all five modeled authentication modes for v1.0.0.
- [x] Approve the six acceptance workflows in `MVP_SCOPE.md`.
- [x] Keep advanced orchestration and future UI capabilities outside the MVP boundary.
### Slices 68 — Completed consistency work
- [x] Make `MVP_SCOPE.md`, requirements, architecture, tasks, roadmap, and slice terminology consistent.
- [x] Ensure every v0.1.0 requirement maps to a slice and a validation criterion.
- [x] Ensure every v1.0.0 requirement maps to a slice and a validation criterion.
- [x] Clearly label all deferred capabilities post-MVP.
- [x] Remove or resolve every open question that could materially change the release boundary.
- [x] Produce a definitive Slice 6 release checklist and record product-owner approval.
@ -285,42 +285,42 @@ Controlled orchestration is not required in the v0.1.0 demonstration. Execution
## 8. Documentation, Packaging, and Release
Slice 8 release packaging now depends on completed Slice 7a authentication/RBAC/publishing, Slice 7b first-run setup, Slice 7c multi-page/scoped-variable behavior, and Slice 7d Visual Editor ribbon polish and documentation. Slice 9 OIDC/SSO remains post-v0.1.0 unless the product owner explicitly changes the boundary.
Slice 8 release packaging now depends on completed Slice 7a authentication/RBAC/publishing, Slice 7b first-run setup, Slice 7c multi-page/scoped-variable behavior, and Slice 7d Visual Editor ribbon polish and documentation. Slice 9 OIDC/SSO remains post-v1.0.0 unless the product owner explicitly changes the boundary.
### Slice 8 — Documentation ownership and reconciliation
- [x] Create and link a unified v0.1.0 roadmap grouped by function and slice.
- [x] Create and link a unified v1.0.0 roadmap grouped by function and slice.
- [x] Designate `docs/` as the authoritative specification location.
- [x] Remove exact duplicate root requirements, architecture, and future-idea documents after verifying links and replacements.
- [x] Reconcile requirements and architecture with the approved MVP scope.
- [ ] Update schema and response-mapping documentation to match canonical runtime behavior.
- [ ] Reconcile `ROADMAP.md`, `CODEX.md`, and all slice handoffs as implementation progresses.
- [x] Update schema and response-mapping documentation to match canonical runtime behavior.
- [x] Reconcile `ROADMAP.md`, `CODEX.md`, and all slice handoffs through v1.0.0 release preparation.
### Slice 8 — User and operator documentation
- [ ] Update README prerequisites, commands, and documentation index.
- [ ] Publish installation, Docker Compose, first-project, Visual Editor, JSON Editor, component, REST Action, template, variable, binding/event, and troubleshooting guides.
- [ ] Publish authentication, secret provisioning, redaction, proxy policy, security, known-limitations, and deployment guidance.
- [ ] Document SQLite backup, persistence, recovery, upgrade, and schema-version policy.
- [x] Update README prerequisites, commands, and documentation index.
- [x] Publish installation, Docker Compose, first-project, Visual Editor, JSON Editor, component, REST Action, template, variable, binding/event, and troubleshooting guides.
- [x] Publish authentication, secret provisioning, redaction, proxy policy, security, known-limitations, and deployment guidance.
- [x] Document SQLite backup, persistence, recovery, upgrade, and schema-version policy.
### Slice 8 — Developer documentation
- [ ] Publish architecture, canonical model, frontend state, runtime state, binding flow, proxy flow, database, test structure, mock-server, and contribution documentation.
- [ ] Publish verified build, test, Docker, and release commands.
- [ ] Publish the final acceptance checklist with links to evidence.
- [ ] Check internal links, paths, examples, and documented commands.
- [x] Publish architecture, canonical model, frontend state, runtime state, binding flow, proxy flow, database, test structure, mock-server, and contribution documentation.
- [x] Publish verified build, test, Docker, and release commands.
- [x] Publish the final acceptance checklist with links to evidence.
- [x] Check internal links, paths, examples, and documented commands.
### Slices 6 and 8 — v0.1.0 packaging
### Slices 6 and 8 — v1.0.0 packaging
- [ ] Review examples, demo, open issues, deferred work, and release criteria.
- [ ] Build a single non-root production image serving the compiled frontend, SPA/published routes, and backend API on one port while retaining the two-container development stack.
- [ ] Publish production Compose/environment assets and anonymously downloadable source releases plus pinned multi-architecture container tags.
- [ ] Add application-owned consistent SQLite backup/restore with encryption keys, manifests, checksums, safety backup, and health verification.
- [ ] Add and validate SkeletonWorks `setup-conductor.sh`, `backup-conductor.sh`, and `restore-conductor.sh` behind Caddy.
- [x] Review examples, demo, open issues, deferred work, and release criteria.
- [x] Build a single non-root production image serving the compiled frontend, SPA/published routes, and backend API on one port while retaining the two-container development stack.
- [ ] Publish production Compose/environment assets and anonymously downloadable source releases plus a pinned Linux/AMD64 v1.0.0 container tag.
- [x] Add application-owned consistent SQLite backup/restore with encryption keys, manifests, checksums, safety backup, and health verification.
- [x] Add and validate SkeletonWorks `setup-conductor.sh`, `backup-conductor.sh`, and `restore-conductor.sh` behind Caddy.
- [ ] Complete fresh-clone, container-only, fresh-host, upgrade, rollback, backup, restore, restart, persistence, and health validation.
- [ ] Prepare release notes and update version references.
- [x] Prepare the repository release notes and update version references; artifact-derived Gitea Release fields remain a publication task.
- [ ] Commit the release documentation and code.
- [ ] Tag `v0.1.0` and push the release commit and tag.
- [ ] Tag `v1.0.0` and push the release commit and tag.
## Post-MVP Backlog

View File

@ -37,13 +37,13 @@ The first manual run passed malformed-JSON Test 1A. Tests 1B1D exposed a fron
Tests 1B1D subsequently passed. Test 3B received HTTP 402 from the external httpbingo endpoint, which is recorded as an unavailable test dependency rather than a Conductor result. The manual procedure now uses a Compose-only local mock and exact server-controlled internal-origin exception. Controlled HTTP 200, one-second delay, and HTTP 503 responses all passed through the proxy; manual Test 3B retest remains pending.
The controlled-fixture continuation passed Tests 15. Test 6A found that JSON Editor omitted the shared validation summary, while 6B was not run because the partial JSON-edit instruction was too vague. JSON Editor now includes the shared summary with regression coverage; 24 frontend suites / 515 tests and production build pass, and Docker was rebuilt. A complete `SLICE5_TEST6B_PROJECT.json` replaces the partial-edit instruction and produces exactly the intended transform compatibility warning. Retest 6A, Test 6B, and cleanup remain pending.
The controlled-fixture continuation passed Tests 15. Test 6A found that JSON Editor omitted the shared validation summary, while 6B was not run because the partial JSON-edit instruction was too vague. JSON Editor now includes the shared summary with regression coverage; 24 frontend suites / 515 tests and production build pass, and Docker was rebuilt. A complete controlled document replaced the partial-edit instruction and produced exactly the intended transform compatibility warning. Retest 6A, Test 6B, and cleanup remained pending at that point.
Retest 6A and prepared-document Test 6B passed, and the user confirmed all tests pass. Cleanup cleared all disposable execution history, deleted project `#14`, removed the mock fixture/internal exception, restored standard Compose, and confirmed healthy backend/frontend plus empty executions, secrets, secret-key configuration, and internal-origin configuration. Manual acceptance is complete; explicit final Slice 5 sign-off remains pending.
## Slice 6 Automated Release Gate — 2026-08-05
Automation and the authoritative manual procedure in `SLICE6_MANUAL_TEST.md` are complete.
Automation and the recorded Slice 6 manual procedure are complete.
Passing evidence:
@ -58,7 +58,7 @@ One release-boundary defect was fixed before this gate: selecting a Table row no
Known release risk: the legacy Create React App dependency tree retains high advisories in build/development tooling with no supported non-breaking `npm audit` fix. This requires a packaging/toolchain decision in Slice 8; it is not recorded as a passing audit.
Automation and human acceptance remain distinct. `SLICE6_MANUAL_TEST.md`, cleanup, and explicit final sign-off passed; Slice 6 is complete.
Automation and human acceptance remain distinct. The Slice 6 manual acceptance, cleanup, and explicit final sign-off passed; Slice 6 is complete.
### Slice 6 manual progress
@ -77,7 +77,7 @@ The user granted explicit final Slice 5 sign-off on 2026-08-04 with the wording:
Actions & Bindings now uses accessible collapsible major sections and independently collapsible action, binding, variable, and secret cards. REST editing is grouped into Identity, Endpoint & authentication, Request parameters, and Request body; the denser request groups start closed. Secret creation is explicit rather than exposing its full form whenever the section opens. Section hiding preserves mounted local editor state, and collapsed issue badges lead to expanded diagnostics.
Focused ActionInspector/SecretManager coverage passes at 18 tests. Full frontend coverage passes at 25 suites / 520 tests, standalone TypeScript passes, and the production build succeeds. Standard Compose was rebuilt successfully. A disposable high-density project, `Slice 6a Density Manual` (`#22`), is prepared for the proportional procedure in `SLICE6a_MANUAL_TEST.md`. Manual acceptance, cleanup, and explicit sign-off remain pending.
Focused ActionInspector/SecretManager coverage passes at 18 tests. Full frontend coverage passes at 25 suites / 520 tests, standalone TypeScript passes, and the production build succeeds. Standard Compose was rebuilt successfully. A disposable high-density project, `Slice 6a Density Manual` (`#22`), was prepared for the local proportional procedure. Manual acceptance, cleanup, and explicit sign-off remained pending at that point.
The user subsequently reported all five manual UX tests pass and that the changes look good. Cleanup deleted project `#22`, and final standard-stack checks returned backend health `ok`, frontend HTTP 200, empty secrets, and empty execution history.

View File

@ -1,12 +1,12 @@
{
"name": "conductor-backend",
"version": "0.1.0",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "conductor-backend",
"version": "0.1.0",
"version": "1.0.0",
"dependencies": {
"ajv": "^8.20.0",
"ajv-formats": "^3.0.1",

View File

@ -1,6 +1,6 @@
{
"name": "conductor-backend",
"version": "0.1.0",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only src/index.ts",

View File

@ -204,7 +204,7 @@ function semanticIssues(doc: JsonObject): ValidationIssue[] {
if (!supportedTriggers.includes(binding.trigger ?? (selectionSource ? 'onChange' : 'onSuccess')))
add(issues, 'BINDING_TRIGGER_UNSUPPORTED', `${path}/trigger`, `Trigger "${binding.trigger}" is not supported for this binding source.`);
if (binding.transform !== undefined)
add(issues, 'BINDING_TRANSFORM_DEFERRED', `${path}/transform`, 'Binding transforms are modeled but are not executed in v0.1.0.', 'warning');
add(issues, 'BINDING_TRANSFORM_DEFERRED', `${path}/transform`, 'Binding transforms are modeled but are not executed in this release.', 'warning');
});
actions.forEach((action, index) => {

View File

@ -1,10 +1,10 @@
services:
conductor:
image: ${CONDUCTOR_IMAGE:-gitea.skeletonworks.online/vwiebe/conductor}:${CONDUCTOR_VERSION:-latest}
image: ${CONDUCTOR_IMAGE:-gitea.skeletonworks.online/vwiebe/conductor}:${CONDUCTOR_VERSION:-v1.0.0}
restart: unless-stopped
init: true
ports:
- "${CONDUCTOR_BIND_ADDRESS:-0.0.0.0}:${CONDUCTOR_PORT:-8080}:8080"
- "${CONDUCTOR_BIND_ADDRESS:-127.0.0.1}:${CONDUCTOR_PORT:-8080}:8080"
environment:
NODE_ENV: production
PORT: 8080

135
docs/ADMIN_GUIDE.md Normal file
View File

@ -0,0 +1,135 @@
# Administrator Guide
This guide covers administration inside Conductor: accounts, sessions, stored credentials, publications, and execution history. For Docker, TLS, configuration keys, backups, recovery, and upgrades, use the [Installation Guide](INSTALL.md) and [Operations Guide](OPERATIONS.md).
## Administrator scope
Conductor has global roles rather than per-project or per-application permissions.
| Principal | Access |
|---|---|
| Anonymous visitor | Active public applications and their anonymous actions only. |
| User | Public and restricted applications in the catalog; own password change. |
| Administrator | All user access plus project authoring, validation, action testing, credentials, execution history, publishing, and user management. |
The backend enforces these boundaries even if someone constructs an API request directly. Conductor v1.0.0 does not provide groups, custom roles, per-application assignments, self-registration, email invitations, or email-based password recovery.
## Initialize a new installation
1. Confirm the host operator has finished the deployment, configured HTTPS, and received a healthy response from `/api/health`. Independent self-hosters can follow the [public installation guide](INSTALL.md).
2. Open the Conductor HTTPS URL in a browser.
3. On **Set up Conductor**, enter a unique username and a password of at least 12 characters. Display name and contact email are optional.
4. Select **Create administrator**. Conductor creates the account and signs it in.
5. Open **Users** and create a second administrator for recovery before authoring production applications.
There are no default credentials. The browser setup is available only while the database contains no users; it closes permanently after the first account is created. Concurrent setup attempts can create at most one first administrator.
If browser setup cannot be used, the host operator can perform the explicit empty-installation bootstrap in [Administrative bootstrap and recovery](OPERATIONS.md#administrative-bootstrap-and-recovery).
## Manage users and sessions
Open **Users** to perform account administration.
### Create an account
Enter a unique username, optional display name and contact email, a temporary password of at least 12 characters, and the `User` or `Admin` role. Communicate the temporary password through an approved private channel.
### Change an account
- Change **Role** to promote or demote an account.
- Toggle **Enabled** to allow or block authentication.
- Edit display name or contact email and leave the field to save it.
- Select **Reset password** to set and confirm a new password.
- Select **Revoke sessions** to sign the account out everywhere.
Disabling an account, changing its role, resetting its password, or explicitly revoking sessions invalidates its existing sessions. Conductor refuses to disable or demote the last enabled administrator.
Users change their own password beneath the application catalog. That operation rotates the current session and revokes their other sessions. Administrators can reset their own account from **Users**, but should keep another working administrator available before doing so.
Account deletion is not exposed in v1.0.0. Disable an account when access should be retained only for historical attribution.
## Manage stored credentials
Open **Actions & Bindings**, then expand **Secrets**.
Supported credential types are:
- Basic authentication username and password;
- Bearer token;
- API-key header name and value; and
- API-key query-parameter name and value.
To create a credential, select **Add secret**, choose the type, enter a descriptive name and its required fields, and save. Conductor returns only metadata after creation; the stored value cannot be viewed again.
To rotate a credential, expand it and select **Replace value**. Enter the complete new credential. Saved project actions retain the same opaque reference.
To remove a credential safely:
1. Find every saved project and active publication that uses it.
2. Remove or replace the reference in each source project, then save the project.
3. Republish each application that should remain live, or unpublish it. Published snapshots are immutable and can retain the old reference until this step is complete.
4. Expand the credential and select **Delete**.
Deletion is blocked by references in saved projects, but v1.0.0 does not perform that same check against immutable published snapshots. Do not delete first and leave a live restricted application with a missing credential.
Credential values are encrypted with `CONDUCTOR_SECRET_KEY`. A usable disaster-recovery archive must contain both the database and its matching key. See the [Secrets Security Model](SECRETS.md) and [Backup and restore](OPERATIONS.md#backup).
## Publish and withdraw applications
Open **Publishing** after saving and validating a source project.
1. Select the source project.
2. Enter a display name and unique URL slug.
3. Choose a visibility:
- **Restricted to users** requires an enabled signed-in account.
- **Public** permits anonymous access and is accepted only when every action uses anonymous authentication.
4. Select **Publish**.
5. Use **Open app** to verify the default page and at least one direct page URL.
Publishing stores an immutable snapshot. Editing or saving the source project does not change the live application. Select **Republish** to atomically replace the snapshot with the current valid saved project and increase its version.
Select **Unpublish** to make the application unavailable without deleting the source project. Republish it to restore access. Active publications prevent deletion of their source project through the backend API.
Published routes are:
```text
/apps/<app-slug>
/apps/<app-slug>/<page-slug>
```
Restricted visibility applies to the whole application. Page navigation settings are not authorization rules.
## Review execution history
Open **Execution History** to inspect recent REST proxy activity. Records persist across restarts and include safe request identity, timing, outcome, upstream status when available, response size, and a bounded redacted preview.
Conductor retains the newest 1,000 executions globally. It does not store request or response headers, cookies, credentials, raw sensitive query values, DNS answers, or stack traces. Treat this as bounded troubleshooting history, not as an immutable enterprise audit log.
**Clear history** permanently removes all execution records. Back up the installation first if those records are needed for later analysis.
## Proxy and internal destinations
Project authors can call public `http` and `https` endpoints that pass Conductor's destination and request policy. Private, loopback, link-local, metadata, and other unsafe address ranges are blocked by default.
An in-application administrator cannot weaken that policy. A host operator may add a reviewed exact origin to `CONDUCTOR_PROXY_INTERNAL_ORIGINS`; wildcards and URL paths are not accepted. Use the procedure for the deployment style in [Production configuration](OPERATIONS.md#production-configuration) and the detailed [Proxy Security Policy](PROXY_SECURITY.md).
## Recover administrative access
Try these options in order:
1. Ask another enabled administrator to reset the account's password, enable it, restore its role if appropriate, and revoke old sessions.
2. If every administrator is inaccessible, ask the host operator to use the guarded recovery command in [Administrative bootstrap and recovery](OPERATIONS.md#administrative-bootstrap-and-recovery).
3. If application data is damaged or missing, follow the full [restore procedure](OPERATIONS.md#restore) instead of creating unrelated accounts.
Operator recovery can target only an existing local administrator. It cannot elevate a user or create an additional administrator after first-run setup.
## Routine administration checklist
- Keep at least two enabled administrators with independently controlled credentials.
- Review active publications and confirm public applications contain no credential-backed actions.
- Rotate upstream credentials using **Replace value**, then test the affected actions.
- Review execution failures without copying sensitive data into tickets or screenshots.
- Confirm scheduled backups complete, copy them off-host, and periodically test a restore.
- Install upgrades only from pinned images after reading release notes and taking a backup.
For symptom-based help, see [Troubleshooting](TROUBLESHOOTING.md). For implemented boundaries, see [Known Limitations](KNOWN_LIMITATIONS.md).

View File

@ -2,7 +2,7 @@
## Architecture
The canonical `ProjectDocument` is shared by Visual Editor, JSON Editor, Preview, validation, persistence, and publication snapshots. React owns authoring and ephemeral runtime state; Express owns authentication, authorization, persistence, credential resolution, proxy policy, validation, and publication execution. SQLite is the v0.1.0 durable store.
The canonical `ProjectDocument` is shared by Visual Editor, JSON Editor, Preview, validation, persistence, and publication snapshots. React owns authoring and ephemeral runtime state; Express owns authentication, authorization, persistence, credential resolution, proxy policy, validation, and publication execution. SQLite is the v1.0.0 durable store.
Development uses two containers/processes for fast React/backend iteration. Production uses `Dockerfile.production`: a multi-stage build copies compiled frontend assets and compiled backend output into one minimal runtime image. Express serves API and SPA fallbacks from the same origin.

View File

@ -1,34 +1,21 @@
# First-Run Administration
On an empty installation, open Conductor in a browser. The setup screen creates the first administrator and signs that administrator in. The setup endpoint closes permanently as soon as any user exists; it is not a registration endpoint.
On an empty installation, finish HTTPS and open Conductor in a browser. The setup screen creates the first administrator and signs that administrator in. Conductor ships with no default username or password.
The setup form requires a unique username and a password of at least 12 characters. Display name and contact email are optional. Passwords are masked, confirmed in the browser, hashed before storage, and never returned or logged.
Initial creation is protected by a short-lived same-site setup cookie/header token, request throttling, and an atomic empty-database check. Concurrent setup attempts can create at most one administrator.
Initial creation is protected by a short-lived same-site setup token, request throttling, and an atomic empty-database check. Concurrent setup attempts can create at most one administrator. The setup endpoint closes permanently as soon as any user exists; it is not a registration endpoint.
## Empty-installation CLI fallback
After signing in:
Browser setup is the normal path. Operators may bootstrap an empty installation non-interactively when browser access is unavailable:
1. Open **Users** and create a second administrator for recovery.
2. Store administrator credentials through an approved private process.
3. Confirm the installation has a current off-host backup before adding projects or stored REST credentials.
```bash
docker compose run --rm \
-e CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME='operator' \
-e CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD='a-unique-password-of-12-or-more-characters' \
backend npm run bootstrap-admin
```
See the [Administrator Guide](ADMIN_GUIDE.md) for account and application administration.
The command refuses weak credentials and makes no change when an enabled administrator already exists.
## CLI fallback and recovery
## Explicit administrator recovery
Browser setup is the normal path. A host operator can explicitly bootstrap an empty database or recover one existing local administrator by running the compiled production command documented in [Administrative bootstrap and recovery](OPERATIONS.md#administrative-bootstrap-and-recovery).
If every administrator is inaccessible, an operator with access to the persisted Conductor data volume may reset one existing local administrator. Stop normal administrative work during recovery and provide secrets only in the private terminal environment:
```bash
docker compose run --rm \
-e CONDUCTOR_ALLOW_ADMIN_RECOVERY='I_UNDERSTAND' \
-e CONDUCTOR_RECOVERY_ADMIN_USERNAME='operator' \
-e CONDUCTOR_RECOVERY_ADMIN_PASSWORD='a-new-unique-password-of-12-or-more-characters' \
backend npm run bootstrap-admin
```
Recovery only targets an existing local administrator, re-enables that account, replaces its password hash, and revokes all of its sessions. It cannot create a new administrator or elevate a normal user. Remove sensitive shell history according to local operator policy and rotate the recovered password after access is restored.
Recovery cannot create another account after setup or elevate a normal user. It targets an existing administrator, re-enables it, replaces its password, and revokes its sessions.

View File

@ -1,77 +1,117 @@
# Production Installation
# Install Conductor on Your Own Server
## Supported installation paths
This guide is for independent self-hosters installing Conductor on an ordinary internet-connected server. It uses the public source bundle, public container image, Docker Compose, and a reverse proxy you control. No SkeletonWorks tooling or registry account is required.
Conductor supports:
The recommended path runs the published container. The tagged source bundle supplies the matching Compose file, environment template, backup/restore scripts, and documentation.
1. A public container installation using `compose.production.yml` and a pinned release image.
2. A reproducible source build using `Dockerfile.production` and `compose.production.build.yml`.
3. SkeletonWorks deployment through `setup-conductor.sh` in the `skeletonworks-scripts` repository.
Use the `v1.0.0` commands below only after the public Gitea Release entry exists. Before publication, do not substitute an older release candidate and treat a missing source tag or image as an incomplete release rather than an installation problem.
The production distribution is one same-origin service. Express serves the compiled React application, `/api`, and refreshable published routes such as `/apps/inventory/details` on internal port 8080. The development-only frontend/backend containers are not production artifacts.
## What you need
## Requirements
- A GNU/Linux `x86_64`/AMD64 server. Conductor v1.0.0 is not published for ARM64.
- Docker Engine with the `docker compose` plugin. Use Docker's [Engine installation guide](https://docs.docker.com/engine/install/) and [Compose plugin guide](https://docs.docker.com/compose/install/linux/) if needed.
- Permission to run Docker commands.
- `curl`, `openssl`, `tar`, `bash`, `realpath`, `find`, `sha256sum`, and GNU `stat`.
- About 1 GiB of memory and 1.5 CPU available with the default limits.
- A domain name whose DNS points to the server.
- Inbound ports 80 and 443 for TLS, and outbound HTTPS access for image pulls and REST destinations.
- Caddy, NGINX, or another reverse proxy on the same host.
- Docker Engine with Compose v2
- Approximately 1 GiB memory and 1.5 CPU available by default
- A persistent Docker volume or host directory for `/data`
- TLS reverse proxy for internet-facing deployments
- Two independently generated persistent keys
These commands assume `docker version` and `docker compose version` succeed without `sudo`. If your Docker installation requires elevated access, apply your normal server policy consistently.
## Public container installation
Download `compose.production.yml` and `.env.production.example` from the same tagged release. Do not mix files from different releases.
Confirm the architecture before continuing:
```bash
mkdir conductor && cd conductor
curl -O https://gitea.skeletonworks.online/vwiebe/conductor/raw/tag/v0.1.0/compose.production.yml
curl -o .env https://gitea.skeletonworks.online/vwiebe/conductor/raw/tag/v0.1.0/.env.production.example
uname -m
```
Edit `.env`:
Continue only if it prints `x86_64` or the equivalent AMD64 name for this release.
```dotenv
CONDUCTOR_SECRET_KEY=<output of openssl rand -hex 32>
CONDUCTOR_SESSION_KEY=<different output of openssl rand -hex 32>
CONDUCTOR_IMAGE=gitea.skeletonworks.online/vwiebe/conductor
CONDUCTOR_VERSION=v0.1.0
CONDUCTOR_BIND_ADDRESS=127.0.0.1
CONDUCTOR_PORT=8080
```
## 1. Download the pinned installation bundle
`CONDUCTOR_SECRET_KEY` encrypts stored REST credentials. Losing or changing it makes those credentials unrecoverable. `CONDUCTOR_SESSION_KEY` protects sessions; changing it logs everyone out. Neither belongs in source control.
Start and verify:
Choose a directory that will remain on the server. The example uses the current user's home directory:
```bash
mkdir -p "$HOME/conductor"
cd "$HOME/conductor"
CONDUCTOR_RELEASE=v1.0.0
curl --fail --location --show-error \
"https://gitea.skeletonworks.online/vwiebe/conductor/archive/${CONDUCTOR_RELEASE}.tar.gz" \
--output conductor-source.tar.gz
tar -xzf conductor-source.tar.gz --strip-components=1
rm conductor-source.tar.gz
```
The `v1.0.0` source tag and the container image's OCI `revision` label must identify the same release commit. The authoritative commit, archive checksums, and image digests are recorded in the Gitea `v1.0.0` Release entry after publication. Keep `compose.production.yml`, `.env`, and `scripts/production/` together so the documented backup and restore commands work.
## 2. Create the persistent configuration
Run this block once. If `.env` already exists from an earlier installation, stop and keep it; overwriting its encryption key can make stored credentials unreadable.
```bash
cd "$HOME/conductor"
test ! -e .env || { echo '.env already exists; leaving it unchanged.' >&2; exit 1; }
umask 077
secret_key="$(openssl rand -hex 32)"
session_key="$(openssl rand -hex 32)"
{
printf 'CONDUCTOR_SECRET_KEY=%s\n' "$secret_key"
printf 'CONDUCTOR_SESSION_KEY=%s\n' "$session_key"
printf 'CONDUCTOR_IMAGE=gitea.skeletonworks.online/vwiebe/conductor\n'
printf 'CONDUCTOR_VERSION=v1.0.0\n'
printf 'CONDUCTOR_BIND_ADDRESS=127.0.0.1\n'
printf 'CONDUCTOR_PORT=8080\n'
printf 'CONDUCTOR_MEM_LIMIT=1g\n'
printf 'CONDUCTOR_CPUS=1.5\n'
printf 'CONDUCTOR_PROXY_INTERNAL_ORIGINS=\n'
} > .env
unset secret_key session_key
chmod 600 .env
```
`CONDUCTOR_SECRET_KEY` encrypts stored REST credentials. The database and this exact key are one recovery set. `CONDUCTOR_SESSION_KEY` protects login sessions; changing it signs everyone out. Never commit `.env`, paste its values into tickets, or include them in screenshots.
The loopback bind keeps port 8080 off the public network. Only the reverse proxy should accept internet traffic.
## 3. Pull and start Conductor
```bash
cd "$HOME/conductor"
docker compose --env-file .env -f compose.production.yml pull
docker compose --env-file .env -f compose.production.yml up -d
for _ in $(seq 1 60); do
if curl --fail --silent http://127.0.0.1:8080/api/health >/dev/null; then
break
fi
sleep 2
done
docker compose --env-file .env -f compose.production.yml ps
curl --fail http://127.0.0.1:8080/api/health
curl --fail --show-error http://127.0.0.1:8080/api/health
```
Open the configured URL. A new database presents the browser first-run administrator screen. Conductor never ships a default username or password.
## Build from source
Use a tagged source archive or checkout:
The final command should return healthy JSON. If it fails, inspect:
```bash
git clone https://gitea.skeletonworks.online/vwiebe/conductor.git
cd conductor
git checkout v0.1.0
cp .env.production.example .env
# Replace both key placeholders.
docker compose --env-file .env \
-f compose.production.yml -f compose.production.build.yml \
up -d --build
docker compose --env-file .env -f compose.production.yml logs --tail=200 conductor
```
The multi-stage build compiles frontend and backend code, prunes development dependencies, includes the matching project schema, and runs as UID/GID 10001.
The v1.0.0 release is complete only after this pull succeeds without a Gitea username, password, or token. Check the Gitea `v1.0.0` Release entry for the published OCI index and AMD64 manifest digests. Do not substitute `latest` or an older release-candidate digest.
## Caddy
## 4. Configure HTTPS
Bind Conductor to loopback and proxy it through Caddy:
Production login and setup cookies are `Secure`, so finish HTTPS before creating the first administrator. Plain HTTP is suitable for the loopback health check, not for normal browser use.
Choose one reverse proxy. The examples assume the proxy runs directly on the Docker host. Replace `conductor.example.com` with your real hostname and create its DNS record first.
### Caddy
Install Caddy using its [official installation guide](https://caddyserver.com/docs/install). Add this site block to `/etc/caddy/Caddyfile`:
```caddyfile
conductor.example.com {
@ -80,17 +120,29 @@ conductor.example.com {
}
```
Caddy provides TLS automatically when DNS and ports 80/443 are correctly configured.
Then validate and reload it:
## NGINX
```bash
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
```
Caddy obtains and renews TLS certificates automatically when DNS and inbound ports 80/443 are correct.
### NGINX
Provision a valid TLS certificate using your normal NGINX process, then proxy every path to Conductor:
```nginx
server {
listen 443 ssl http2;
listen 443 ssl;
server_name conductor.example.com;
# Configure ssl_certificate and ssl_certificate_key for this hostname.
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -98,31 +150,91 @@ server {
}
```
Configure certificates using the operator's normal NGINX/TLS process.
Validate and reload NGINX after placing the block in the configuration used by your distribution. Configure the port-80 server to redirect HTTP to HTTPS.
If the reverse proxy runs on another host, do not expose port 8080 to the whole internet. Bind it to a private interface and restrict that port to the proxy host with network and firewall rules.
## 5. Create the first administrator
Open the final URL, for example:
```text
https://conductor.example.com
```
The first-run screen asks for a username and a password of at least 12 characters. Display name and contact email are optional. Conductor creates that administrator and closes first-run setup permanently. There are no default credentials.
Create a second administrator from **Users** before relying on the installation. Application administration is covered in the [Administrator Guide](ADMIN_GUIDE.md).
## 6. Smoke-test persistence and routing
1. Sign in and create a small project in **Visual Editor**.
2. Save it, restart the container, and sign in again:
```bash
cd "$HOME/conductor"
docker compose --env-file .env -f compose.production.yml restart conductor
```
3. Load the saved project and confirm it persisted.
4. Publish it and open both `/apps/<app-slug>` and a direct `/apps/<app-slug>/<page-slug>` URL in new browser tabs.
The editor, API, and published routes should all use the same HTTPS origin. A direct deep link must not return the reverse proxy's 404 page.
## Internal REST destinations
The proxy denies private/internal destinations by default. `CONDUCTOR_PROXY_INTERNAL_ORIGINS` is an optional comma-separated allowlist of exact origins. Add only reviewed origins, for example `https://api.internal.example.com:443`. It does not accept wildcard hosts.
Conductor allows public HTTP/HTTPS destinations that pass its proxy policy and denies private or internal networks by default. If an application must call an internal API, add only its reviewed exact origin to `.env`, for example:
## SkeletonWorks
On a prepared SkeletonWorks host:
```bash
sudo bash /opt/skeletonworks/scripts/setup-conductor.sh \
--domain example.com \
--image gitea.skeletonworks.online/vwiebe/conductor:v0.1.0 \
--restartcaddy
```dotenv
CONDUCTOR_PROXY_INTERNAL_ORIGINS=https://api.internal.example.com:443
```
The script creates `/opt/skeletonworks/conductor/conductor.example.com`, preserves keys across reruns, joins `skeletonworks_net`, installs a Caddy block and backup cron entry, waits for health, and emits a JSON result. Prefer immutable version, Git-SHA, or digest references over `latest`.
Multiple origins are comma-separated. Wildcards, URL paths, credentials, and IP literals are not accepted. Apply a configuration change with:
## Uninstalling
```bash
docker compose --env-file .env -f compose.production.yml up -d
```
Stopping/removing containers does not remove the named data volume:
Read [Proxy Security](PROXY_SECURITY.md) before adding an exception.
## Back up before real use
The installation bundle includes the application-owned online backup script:
```bash
cd "$HOME/conductor"
scripts/production/backup-conductor.sh \
--compose-file compose.production.yml \
--env-file .env \
--backup-dir ./backups \
--retention-days 7
```
Copy the resulting archive off the server and protect it like a password; it includes the database and recovery keys. Follow [Production Operations](OPERATIONS.md) for verified restore, upgrade, rollback, health, and log procedures.
## Build from source instead
The downloaded tag is a complete source tree. To build the production image locally rather than pull the public image, create `.env` as above and run:
```bash
docker compose --env-file .env \
-f compose.production.yml \
-f compose.production.build.yml \
up -d --build
```
This multi-stage build downloads Node packages, compiles the React frontend and TypeScript backend, and runs the same non-root production service. AMD64 is the validated release architecture; an ARM64 source build is not yet a supported release path.
Do not use `docker-compose.yml` for production. It is the two-container development environment.
## Stop or uninstall
Stop and remove the application container while preserving its named data volume:
```bash
docker compose --env-file .env -f compose.production.yml down
```
Do not add `--volumes` unless a verified backup exists and permanent data deletion is intended.
Do not add `--volumes` unless permanent data deletion is intentional and a verified off-host backup exists. Retain `.env` with the backup set even after removing the container.
For common failures, see [Troubleshooting](TROUBLESHOOTING.md).

View File

@ -1,4 +1,4 @@
# Known Limitations for v0.1.0
# Known Limitations for v1.0.0
- SQLite supports one Conductor instance with a persistent local volume; active/active replicas and PostgreSQL are not supported.
- Local username/password authentication is the release provider. OIDC/SSO is planned for Slice 9.
@ -9,5 +9,8 @@
- REST proxy authentication supports Anonymous, Basic, Bearer, API-key header, and API-key query. OAuth 2.0, mTLS, and custom auth are deferred.
- Workflow orchestration, action graphs, loops, retries, and long-running jobs are out of scope.
- Binding transforms and advanced expression languages are deferred.
- The release image targets `amd64` and `arm64` only after both pass the native SQLite build/smoke gate.
- The `v1.0.0` production image supports Linux/AMD64 only. ARM64 publication remains blocked on a native SQLite build/smoke runner.
- The **Projects** navigation item is a placeholder. Create, save, update, and load projects from the Visual or JSON Editor toolbar; deletion remains API-only.
- Component names are validated within a page, but project-wide unique names are recommended because template and binding paths do not include a page qualifier.
- Page-variable scope records intended ownership, but v1.0.0 does not fully reject or prevent cross-page variable references. Keep each page-scoped variable on its declared page.
- Backups are local archives by default; operators must arrange off-host copies and retention appropriate to their recovery objectives.

View File

@ -1,4 +1,4 @@
# Conductor v0.1.0 Requirements Traceability
# Conductor v1.0.0 Requirements Traceability
## Purpose
@ -6,7 +6,7 @@ This matrix maps every release-critical requirement area in `docs/REQUIREMENTS.m
## Release-critical requirements
| ID | v0.1.0 requirement area | Owning slice | Validation criterion and evidence | Status |
| ID | v1.0.0 requirement area | Owning slice | Validation criterion and evidence | Status |
|---|---|---|---|---|
| R1 | Browser-based application, React frontend, backend API, SQLite persistence, and Docker Compose deployment | Slices 1, 6, 8 | Production builds, Compose startup/health/restart/persistence, backup/restore in `docs/RELEASE_VALIDATION.md` and `TESTING.md` | Accepted |
| R2 | Canonical JSON project definition shared by Visual Editor, JSON Editor, Preview, persistence, and validation | Slices 2, 5, 6 | Schema matrix, canonical round trips, cross-view synchronization, save/reload/restart tests | Accepted |
@ -21,7 +21,7 @@ This matrix maps every release-critical requirement area in `docs/REQUIREMENTS.m
| R11 | Central schema/semantic validation, atomic persistence, actionable cross-view diagnostics, and unsaved-edit preservation | Slices 5, 6 | Backend rollback/version/semantic tests and Slice 5 manual failure/recovery acceptance | Accepted |
| R12 | Preview runtime with loading, empty, success, upstream failure, mapping failure, retry/recovery, and ephemeral state | Slices 2, 5, 6 | Preview suites and all six deterministic manual workflows | Accepted |
| R13 | Save/load, portable JSON definition, backend/full-stack restart persistence, runtime reset, and SQLite backup/recovery | Slices 2, 5, 6 | Canonical round-trip tests, E2E save/reload, restart and offline backup/restore evidence | Accepted |
| R14 | Accessible, scannable Actions & Bindings authoring with progressive disclosure and preserved local drafts | Slice 6a | 25 frontend suites / 520 tests and `SLICE6a_MANUAL_TEST.md` acceptance | Accepted |
| R14 | Accessible, scannable Actions & Bindings authoring with progressive disclosure and preserved local drafts | Slice 6a | 25 frontend suites / 520 tests and the accepted manual result recorded in `TESTING.md` | Accepted |
| R15 | Local authentication, secure sessions, global admin/user RBAC, admin-only authoring, and user lifecycle management | Slice 7a | Backend integration security matrix, frontend regression suite, and accepted manual admin/user workflows | Accepted |
| R16 | Immutable standalone published applications with public/authenticated visibility and server-owned published action execution | Slice 7a | Server-snapshot integration coverage and accepted public/restricted publishing workflows | Accepted |
| R17 | A fresh installation creates its initial administrator through a secure browser first-run flow without requiring Docker commands | Slice 7b | Atomic setup/security integration tests, frontend setup/password tests, recovery verification, and accepted manual workflow | Accepted |
@ -33,16 +33,16 @@ This matrix maps every release-critical requirement area in `docs/REQUIREMENTS.m
| Workflow | Primary requirements | Owning validation slice | Evidence |
|---|---|---|---|
| Workflow Launcher | R2R6, R11R13 | Slice 6 | `SLICE6_MANUAL_TEST.md` Test 1 and deterministic E2E |
| Dependent Data | R5, R6, R11, R12 | Slice 6 | `SLICE6_MANUAL_TEST.md` Test 2 and runtime tests |
| Read-Only Dashboard | R3, R5, R6, R12 | Slice 6 | `SLICE6_MANUAL_TEST.md` Test 3 and deterministic E2E |
| Authenticated Request | R4, R7R10 | Slice 6 | `SLICE6_MANUAL_TEST.md` Test 5 and backend integration |
| JSON Editing and Persistence | R1, R2, R11, R13 | Slice 6 | `SLICE6_MANUAL_TEST.md` Tests 4 and 6 |
| Failure Handling | R9R12 | Slice 6 | `SLICE6_MANUAL_TEST.md` Test 4 and Slice 5 recovery evidence |
| Workflow Launcher | R2R6, R11R13 | Slice 6 | Accepted workflow result in `TESTING.md` and deterministic E2E |
| Dependent Data | R5, R6, R11, R12 | Slice 6 | Accepted workflow result in `TESTING.md` and runtime tests |
| Read-Only Dashboard | R3, R5, R6, R12 | Slice 6 | Accepted workflow result in `TESTING.md` and deterministic E2E |
| Authenticated Request | R4, R7R10 | Slice 6 | Accepted workflow result in `TESTING.md` and backend integration |
| JSON Editing and Persistence | R1, R2, R11, R13 | Slice 6 | Accepted JSON/persistence results in `TESTING.md` |
| Failure Handling | R9R12 | Slice 6 | Accepted recovery results in `TESTING.md` and Slice 5 evidence |
## Explicit post-MVP classifications
The following capabilities are not release requirements. Their presence in future-oriented requirements or architecture text does not block v0.1.0:
The following capabilities are not release requirements. Their presence in future-oriented requirements or architecture text does not block v1.0.0:
- Provider-neutral AI assistance, including chat, generation, explanation, documentation, and refactoring
- IBM Bob, watsonx, or any provider-specific AI dependency
@ -61,4 +61,4 @@ The following capabilities are not release requirements. Their presence in futur
## Governance rule
`MVP_SCOPE.md` controls the release boundary. A new capability becomes release-blocking only through an explicit product-owner scope decision followed by updates to this matrix, `ROADMAP.md`, the owning slice, and its validation criteria. Aspirational or compatibility-only schema text does not silently expand v0.1.0.
`MVP_SCOPE.md` controls the release boundary. A new capability becomes release-blocking only through an explicit product-owner scope decision followed by updates to this matrix, `ROADMAP.md`, the owning slice, and its validation criteria. Aspirational or compatibility-only schema text does not silently expand v1.0.0.

View File

@ -6,6 +6,44 @@ All durable application state is stored in `/data/conductor.db`: projects, users
The database alone is not a complete recovery set. A usable backup must include the exact `CONDUCTOR_SECRET_KEY` that encrypted stored credentials. Production backup archives therefore include the database, `.env`, Compose metadata, a manifest, and checksums. Treat archives as secrets and copy them off-host.
## Production configuration
The public Compose installation reads `.env`. Keep it mode `0600`, exclude it from source control, and retain it with the disaster-recovery set.
| Variable | Purpose and operating rule |
|---|---|
| `CONDUCTOR_SECRET_KEY` | Required 32-byte encryption key encoded as 64 hexadecimal characters or base64. Generate once and preserve it with the database. Changing or losing it makes existing stored credentials unreadable. |
| `CONDUCTOR_SESSION_KEY` | Required value of at least 32 bytes used to protect sessions. Generate independently from the encryption key. Changing it signs everyone out. |
| `CONDUCTOR_IMAGE` | Public registry/repository name without a tag. |
| `CONDUCTOR_VERSION` | Pinned published image tag. Do not use a moving `latest` tag for a controlled installation. |
| `CONDUCTOR_BIND_ADDRESS` | Use `127.0.0.1` when the reverse proxy runs on the same host. |
| `CONDUCTOR_PORT` | Host loopback port forwarded to container port 8080. |
| `CONDUCTOR_MEM_LIMIT`, `CONDUCTOR_CPUS` | Container resource ceilings. Increase deliberately after measuring demand. |
| `CONDUCTOR_PROXY_INTERNAL_ORIGINS` | Optional comma-separated exact origins approved to reach private/internal networks. It accepts schemes, hostnames, and effective ports—not wildcards, paths, credentials, or IP literals. |
Production refuses to start if either required key is absent or invalid. Generate them independently with `openssl rand -hex 32`; never paste their output into documentation, tickets, or screenshots.
After changing a non-secret configuration value, recreate the service and verify health:
```bash
docker compose --env-file .env -f compose.production.yml up -d
curl --fail http://127.0.0.1:8080/api/health
```
For a SkeletonWorks deployment, edit `/opt/skeletonworks/conductor/<fqdn>/.env`, recreate that stack, and check its HTTPS health endpoint:
```bash
sudoedit /opt/skeletonworks/conductor/conductor.example.com/.env
sudo docker compose \
-f /opt/skeletonworks/conductor/conductor.example.com/docker-compose.yml \
up -d
curl --fail https://conductor.example.com/api/health
```
The current SkeletonWorks setup script preserves the two keys in `.secrets`, but rewrites `CONDUCTOR_PROXY_INTERNAL_ORIGINS` to an empty value when it is rerun. Until that installer accepts and preserves an internal-origin setting, review and reapply the intended value after every setup or upgrade rerun before testing affected applications.
Do not casually rotate `CONDUCTOR_SECRET_KEY`; v1.0.0 has no online credential re-encryption procedure. Read [Secrets](SECRETS.md) and [Proxy Security](PROXY_SECURITY.md) before changing key or internal-origin policy.
## Backup
From a source/release directory:
@ -61,6 +99,88 @@ sudo /opt/skeletonworks/scripts/restore-conductor.sh \
Never combine a database with a different encryption key. A checksum-valid but mismatched key cannot decrypt stored REST credentials.
## Administrative bootstrap and recovery
Browser setup is the normal way to create the first administrator. The following fallback works only while the database contains no users. It invokes the compiled command inside the running production service:
```bash
read -r -p 'New administrator username: ' CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME
read -r -s -p 'New administrator password (12+ characters): ' CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD
printf '\n'
export CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD
docker compose --env-file .env -f compose.production.yml exec -T \
-e CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME \
-e CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD \
conductor node dist/scripts/bootstrapAdmin.js
unset CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD
```
If every administrator is inaccessible, recover one existing local administrator. Recovery cannot create an account or elevate a user. It re-enables the named administrator, replaces the password hash, and revokes that account's sessions:
```bash
read -r -p 'Existing administrator username: ' CONDUCTOR_RECOVERY_ADMIN_USERNAME
read -r -s -p 'New administrator password (12+ characters): ' CONDUCTOR_RECOVERY_ADMIN_PASSWORD
printf '\n'
export CONDUCTOR_RECOVERY_ADMIN_USERNAME CONDUCTOR_RECOVERY_ADMIN_PASSWORD
export CONDUCTOR_ALLOW_ADMIN_RECOVERY=I_UNDERSTAND
docker compose --env-file .env -f compose.production.yml exec -T \
-e CONDUCTOR_ALLOW_ADMIN_RECOVERY \
-e CONDUCTOR_RECOVERY_ADMIN_USERNAME \
-e CONDUCTOR_RECOVERY_ADMIN_PASSWORD \
conductor node dist/scripts/bootstrapAdmin.js
unset CONDUCTOR_ALLOW_ADMIN_RECOVERY CONDUCTOR_RECOVERY_ADMIN_USERNAME CONDUCTOR_RECOVERY_ADMIN_PASSWORD
```
Run recovery from a private operator terminal, confirm the target carefully, and clear any terminal capture governed by local policy. Create and retain a second enabled administrator so routine recovery can remain in the browser.
For SkeletonWorks, run the corresponding command from the stack directory in a root shell so the password variables are available to Compose. For an empty-installation bootstrap:
```bash
sudo -i
cd /opt/skeletonworks/conductor/conductor.example.com
read -r -p 'New administrator username: ' CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME
read -r -s -p 'New administrator password (12+ characters): ' CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD
printf '\n'
export CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD
docker compose -f docker-compose.yml exec -T \
-e CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME \
-e CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD \
conductor node dist/scripts/bootstrapAdmin.js
unset CONDUCTOR_BOOTSTRAP_ADMIN_USERNAME CONDUCTOR_BOOTSTRAP_ADMIN_PASSWORD
exit
```
For guarded recovery of an existing administrator:
```bash
sudo -i
cd /opt/skeletonworks/conductor/conductor.example.com
read -r -p 'Existing administrator username: ' CONDUCTOR_RECOVERY_ADMIN_USERNAME
read -r -s -p 'New administrator password (12+ characters): ' CONDUCTOR_RECOVERY_ADMIN_PASSWORD
printf '\n'
export CONDUCTOR_RECOVERY_ADMIN_USERNAME CONDUCTOR_RECOVERY_ADMIN_PASSWORD
export CONDUCTOR_ALLOW_ADMIN_RECOVERY=I_UNDERSTAND
docker compose -f docker-compose.yml exec -T \
-e CONDUCTOR_ALLOW_ADMIN_RECOVERY \
-e CONDUCTOR_RECOVERY_ADMIN_USERNAME \
-e CONDUCTOR_RECOVERY_ADMIN_PASSWORD \
conductor node dist/scripts/bootstrapAdmin.js
unset CONDUCTOR_ALLOW_ADMIN_RECOVERY CONDUCTOR_RECOVERY_ADMIN_USERNAME CONDUCTOR_RECOVERY_ADMIN_PASSWORD
exit
```
Replace `conductor.example.com` with the deployed FQDN. Browser setup and another enabled administrator remain the preferred paths.
## Upgrade
1. Read release notes and compatibility warnings.

View File

@ -4,7 +4,7 @@
The REST proxy accepts destinations and request templates from project authors. Treat those values, DNS answers, redirects, upstream headers, bodies, and errors as untrusted. The proxy must prevent access to the Conductor host and private infrastructure, credential forwarding to a different origin, request smuggling, unbounded memory use, and disclosure through responses, logs, or execution history.
Conductor v0.1.0 is single-user software. This policy does not provide tenant isolation, RBAC, malware inspection, TLS interception, or protection from an already-compromised backend process.
Conductor enforces global `admin` and `user` roles. Only administrators can author or directly test REST actions; published execution resolves actions from server-owned snapshots. This policy does not isolate mutually hostile administrators, inspect malware, intercept upstream TLS, or protect an already-compromised backend process.
## Destination contract
@ -26,6 +26,6 @@ Conductor v0.1.0 is single-user software. This policy does not provide tenant is
## Execution-history contract
SQLite stores the most recent 1,000 executions globally. Each record contains its timestamp, optional project identity supplied by the runtime, action ID/name, method, sanitized URL (query values and embedded credentials redacted), upstream status when available, duration, outcome, safe error code/message, response byte count, truncation flag, content type, and a redacted preview no larger than 2 KiB. Oldest records are deleted after insertion.
Administrator-only execution history in SQLite stores the most recent 1,000 executions globally. Each record contains its timestamp, optional project identity supplied by the runtime, action ID/name, method, sanitized URL (query values and embedded credentials redacted), upstream status when available, duration, outcome, safe error code/message, response byte count, truncation flag, content type, and a redacted preview no larger than 2 KiB. Oldest records are deleted after insertion.
History persists across restart. `GET /api/executions` supports project, action, outcome, and status filters with a maximum page size of 100. `DELETE /api/executions` clears all history and returns no records. History never stores request or response headers, cookies, credential values, sensitive query values, stack traces, DNS results, resolved addresses, or secret-resolution details.

View File

@ -1,45 +1,59 @@
# Release Construction and Publication
## Image identity
This procedure publishes the Conductor application release. The application version is `v1.0.0`; canonical project documents continue to use schema version `0.1.0`.
## Image identity and architecture
Each production image must correlate to one source revision and include OCI version, revision, creation-time, source, title, and description labels.
Release tags:
Release tags are:
- `vX.Y.Z`: immutable release
- `git-<12-character-sha>`: immutable revision identity
- `latest`: optional convenience pointer; never recommended for controlled deployment
- `vX.Y.Z`: immutable application release;
- `git-<12-character-sha>`: immutable source-revision identity; and
- `latest`: optional convenience pointer, never used in controlled installation instructions.
Conductor v1.0.0 supports `linux/amd64`. ARM64 is not a supported v1.0.0 artifact because its native SQLite build has not completed the required release smoke test.
## Build locally
From a clean release commit:
```bash
scripts/release-image.sh --version v0.1.0 --platforms linux/amd64
scripts/release-image.sh --version v1.0.0 --platforms linux/amd64
```
## Publish multi-architecture images
Run the production lifecycle tests against that image before publication.
Authenticate to the registry using a scoped token, then:
## Publish the image
Use exactly one publication path. Do not allow an automated tag job and a manual push to race on the same immutable tag.
The tag-triggered Gitea workflow builds and pushes `v1.0.0` and `git-<sha>` image tags. It requires an available compatible runner and configured registry credentials. It publishes container images only; it does not create the human-facing Gitea Release entry.
If a controlled manual publication is required, first ensure no tag-triggered workflow can later rebuild or overwrite the tag. Authenticate with a scoped publisher token, check out the exact approved release commit, and run:
```bash
docker login gitea.skeletonworks.online
scripts/release-image.sh --version v0.1.0 --push
scripts/release-image.sh \
--version v1.0.0 \
--platforms linux/amd64 \
--push
```
The default published platforms are `linux/amd64,linux/arm64`. Both must successfully compile and load the native `better-sqlite3` dependency. If a target cannot pass build and smoke tests, omit it and state that explicitly in release notes.
Registry authentication is for publishers only. Consumers must be able to pull the final release without credentials.
## Release checklist
## Release sequence
1. Clean checkout of the intended commit.
2. Governance, schema, frontend, backend, and browser suites pass.
3. Production image builds without local dependencies.
4. Missing-key startup fails; configured startup becomes healthy.
5. Root UI, `/api/health`, and published deep-link refresh return correctly.
6. Fresh first-run administrator setup passes with no default credentials.
7. Restart preserves data.
8. Online backup, checksum verification, destructive restore, and marker recovery pass.
9. Upgrade and rollback drill passes with pinned images and matching database backup.
10. Public source archive and container image are anonymously downloadable.
11. Release notes list image digests, architectures, known limitations, and upgrade instructions.
12. Tag and push only after explicit release approval.
1. Prepare one clean release commit containing the code, documentation, production assets, and `1.0.0` package metadata.
2. Run governance, documentation, schema, frontend, backend, browser, and production lifecycle suites.
3. Confirm missing-key startup fails and configured startup, health, root UI, and published deep links pass.
4. Confirm first-run administration, restart persistence, online backup, verified restore, upgrade, and rollback behavior.
5. Obtain explicit release approval.
6. Create the immutable annotated `v1.0.0` source tag on the approved commit and push it, using the automated image path only when its runner is available.
7. Publish the `v1.0.0` and matching `git-<12-character-sha>` Linux/AMD64 images through the single selected publication path.
8. From an unauthenticated environment, download the tagged source archive and pull the container image.
9. Confirm the OCI `version` is `v1.0.0`, the OCI `revision` matches the tagged source commit, and the AMD64 image passes its smoke test.
10. Create the Gitea Release entry for `v1.0.0` and record the source commit, archive checksums, OCI index and AMD64 manifest digests, Git-SHA image tag, supported architecture, anonymous verification result, limitations, and upgrade/rollback notes.
11. Complete the post-publication checks in [Release Validation](RELEASE_VALIDATION.md) and record the external/manual acceptance result; publication is not complete while any final artifact check is blocked or failed.
Registry authentication is required only for publishing. Consumers must not require credentials for a public release; if the Gitea package cannot be pulled anonymously, publish the identical digest to a supported public registry and use it in public installation examples.
If Gitea cannot provide anonymous image pulls, publish the same release image to a supported public registry, verify it anonymously, and update the installation guide and release entry before sign-off.

View File

@ -0,0 +1,71 @@
# Conductor v1.0.0 Release Notes
Conductor v1.0.0 is the first production application release. It promotes the completed and accepted MVP feature set without changing the canonical project-document format.
## Release identity
| Item | Value |
|---|---|
| Application version | `v1.0.0` |
| Source tag | `v1.0.0` |
| Container | `gitea.skeletonworks.online/vwiebe/conductor:v1.0.0` |
| Supported container platform | Linux/AMD64 |
| Project-document schema | `0.1.0` |
Application and project-schema versions are independent. Existing valid `schemaVersion: "0.1.0"` projects remain the supported format in Conductor v1.0.0; this release does not require a project-document migration.
## Highlights
- Visual and JSON authoring over one canonical project document.
- Eleven supported UI components with multi-page authoring and published deep links.
- REST actions, runtime request templates, typed variable declarations, response bindings, and Preview execution.
- Anonymous, Basic, Bearer, API-key header, and API-key query authentication for REST actions.
- Encrypted server-side stored credentials with opaque project references.
- Default-deny outbound proxy policy, bounded responses, safe errors, and sanitized execution history.
- Local administrator/user accounts, secure sessions, first-run administrator setup, and immutable public or restricted application snapshots.
- A hardened single-container production service with persistent SQLite state, health checks, generated-key requirements, backup, verified restore, upgrade, and rollback procedures.
- Public self-hosting documentation plus SkeletonWorks setup, backup, and restore integration.
## Install and operate
- New independent installations: [Installation Guide](INSTALL.md)
- Application administration: [Administrator Guide](ADMIN_GUIDE.md)
- Project authoring and use: [User Guide](USER_GUIDE.md)
- Backup, restore, upgrade, and rollback: [Production Operations](OPERATIONS.md)
- Security boundaries: [Secrets](SECRETS.md), [Proxy Security](PROXY_SECURITY.md), and [Authorization and Publishing Security](AUTHORIZATION_AND_PUBLISHING_SECURITY.md)
Conductor ships with no default credentials. Production browser access requires HTTPS because authentication and setup cookies are marked `Secure`.
## Upgrade from v0.1.0-rc.1
1. Create a verified backup and copy it off-host.
2. Preserve the existing `.env`, especially `CONDUCTOR_SECRET_KEY` and `CONDUCTOR_SESSION_KEY`.
3. Change the pinned image version to `v1.0.0`.
4. Pull and recreate the service.
5. Verify health, sign-in, a saved project, and a published deep link.
The project schema remains `0.1.0`, so the application-version promotion does not require rewriting saved project documents. Keep the pre-upgrade image reference and matching backup until the upgrade has passed its smoke tests.
## Principal limitations
- The v1.0.0 production container target is Linux/AMD64 only.
- SQLite supports one Conductor application instance; active/active replicas are not supported.
- Authentication uses local accounts; OIDC/SSO is planned after v1.0.0.
- Roles are global `admin` and `user`; custom roles and per-application assignments are not implemented.
- Advanced workflows, transforms, expression languages, retries, and action graphs are deferred.
See [Known Limitations](KNOWN_LIMITATIONS.md) for the complete boundary.
## Authoritative publication record
The public Gitea Release entry for `v1.0.0` must record values generated during final publication rather than guessed in source documentation:
- tagged source commit;
- source archive checksums;
- OCI index digest and Linux/AMD64 manifest digest;
- matching `git-<12-character-sha>` image tag;
- OCI version and revision correlation;
- anonymous source-download and image-pull results; and
- final publication date and release sign-off.
The release is not complete until the `v1.0.0` source tag, container image, and Gitea Release entry exist publicly and the post-publication gates in [Release Validation](RELEASE_VALIDATION.md) pass.

View File

@ -1,4 +1,4 @@
# Conductor v0.1.0 Release Validation
# Conductor v1.0.0 Release Validation
## Release-critical layers
@ -63,7 +63,7 @@ The backend integration suite binds isolated localhost ports. In restricted comm
- destructive restore resets ownership/mode, becomes healthy, and recovers a marker record;
- cleanup removes the disposable container, network, volume, environment, and archive.
The release image workflow publishes immutable version and Git-SHA tags with OCI metadata, SBOM, and provenance for `linux/amd64` and `linux/arm64`. Before release approval, an unauthenticated client must pull the final digest. If Gitea denies anonymous package pulls, the same digest must be published to the documented public fallback registry.
The v1.0.0 release image workflow publishes immutable version and Git-SHA tags with OCI metadata, SBOM, and provenance for `linux/amd64`. ARM64 is not a supported v1.0.0 release architecture. Anonymous source download, anonymous image pull, exact digest capture, and source/OCI-revision correlation are post-publication gates: they cannot be claimed before the final tag and image exist. If Gitea denies anonymous package pulls, the same release image must be published to the documented public fallback registry.
## Manual gate

View File

@ -4,7 +4,7 @@
## Scope Authority
`MVP_SCOPE.md` is the approved v0.1.0 release boundary. `ROADMAP.md` maps that boundary to implementation slices, and `docs/MVP_TRACEABILITY.md` maps each release-critical requirement area to validation evidence. Statements labeled **Post-MVP** are intentionally excluded from v0.1.0 and do not block release.
`MVP_SCOPE.md` is the approved MVP and v1.0.0 release boundary. `ROADMAP.md` maps that boundary to implementation slices, and `docs/MVP_TRACEABILITY.md` maps each release-critical requirement area to validation evidence. Statements labeled **Post-MVP** are intentionally excluded from v1.0.0 and do not block release.
## 1. Purpose
@ -12,7 +12,7 @@ Build a lightweight UI builder that allows users to create simple frontend appli
The tool should allow users to drag and drop UI elements onto a canvas, configure those elements, connect them to REST API calls, and allow one UI element to update another based on API responses or user interaction.
The v0.1.0 application has no AI dependency. Provider-neutral AI assistance may generate, configure, document, or refine project definitions in a future post-MVP increment.
The v1.0.0 application has no AI dependency. Provider-neutral AI assistance may generate, configure, document, or refine project definitions in a future post-MVP increment.
---
@ -184,7 +184,7 @@ Each REST API action shall support:
* JSON request bodies where the selected method sends a body
* JSON and safely represented non-JSON responses through the proxy
The backend applies the fixed v0.1.0 proxy-policy timeout. Per-action timeout and expected-response-format controls are post-MVP because schema version `0.1.0` has no such fields.
The backend applies the fixed v1.0.0 proxy-policy timeout. Per-action timeout and expected-response-format controls are post-MVP because schema version `0.1.0` has no such fields.
## 6.5 Authentication Support
@ -249,7 +249,7 @@ Example:
## 6.8 AI Assistance — Post-MVP
AI assistance is not a v0.1.0 requirement. Any future integration must be provider-neutral and may assist users by:
AI assistance is not a v1.0.0 requirement. Any future integration must be provider-neutral and may assist users by:
* Suggesting UI layouts from a natural language prompt.
* Generating REST API action definitions.
@ -333,7 +333,7 @@ Conductor shall provide a JSON Editor for advanced users.
The JSON Editor shall allow users to directly edit the project's canonical JSON document.
The v0.1.0 JSON Editor provides:
The v1.0.0 JSON Editor provides:
* Schema validation
* Error reporting
@ -421,7 +421,7 @@ A binding contains:
* Target
* Trigger event
The schema-retained `transform` field and configurable per-binding error policies are compatibility/future shapes and are not executed in v0.1.0.
The schema-retained `transform` field and configurable per-binding error policies are compatibility/future shapes and are not executed in v1.0.0.
## 7.6 Project Definition Document
@ -460,7 +460,7 @@ Example capabilities enabled by this approach include:
* Generating documentation from the project definition.
* Generating frontend code from the project definition.
Conductor publishes the v0.1.0 project schema at `shared/schemas/conductor-project.schema.json` for validation, tooling, and interoperability.
Conductor publishes project schema version `0.1.0` at `shared/schemas/conductor-project.schema.json` for validation, tooling, and interoperability.
---
@ -575,12 +575,12 @@ Potential future enhancements:
## 12. Resolved MVP Decisions
* Conductor v0.1.0 is a standalone web application deployed locally or behind an operator-managed reverse proxy.
* Conductor v1.0.0 is a standalone web application deployed locally or behind an operator-managed reverse proxy.
* REST calls execute through the backend proxy; credential-backed calls never execute directly from the browser.
* Secrets use encrypted server-side storage and opaque project references as documented in `docs/SECRETS.md`.
* All five modeled authentication modes are required.
* OpenAPI import, generated React output, and provider-neutral AI assistance are post-MVP.
* The primary v0.1.0 output is a working hosted UI backed by a portable canonical project definition.
* The primary v1.0.0 output is a working hosted UI backed by a portable canonical project definition.
* Sanitized local execution history is required; enterprise audit retention and SIEM integration are post-MVP.
* Proxy destinations are governed by the default-deny policy and explicit exceptions in `docs/PROXY_SECURITY.md`; arbitrary unsafe URLs are not allowed.
* Production-endpoint approval workflows are an operator policy and post-MVP product capability.

View File

@ -1,5 +1,3 @@
# SCHEMA.md
# Conductor Project JSON Schema
This document describes the canonical JSON schema for Conductor project definitions and explains how to use it.
@ -99,6 +97,8 @@ A UI element placed on a page canvas. Required fields: `id`, `type`, `name`, `po
Allowed `type` values:
`Button` · `TextInput` · `TextArea` · `Dropdown` · `Checkbox` · `RadioGroup` · `Label` · `Table` · `JsonViewer` · `StatusPanel` · `Container`
Component names are schema-unique within a page. Because runtime template and binding paths do not carry a page ID, use project-wide unique names in authored applications to avoid ambiguous references.
```json
{
"id": "cmp_launch_btn",
@ -181,7 +181,7 @@ New response mappings belong in top-level `project.bindings`, not inside the act
| `url` | `string` | ✅ | Target URL; may use executed component/variable templates. |
| `headers` | `object` | — | Request headers; values may use executed templates. |
| `queryParameters` | `object` | — | Query parameters; values may use executed templates. |
| `pathParameters` | `object` | — | Static path substitutions; runtime templates are not supported here. |
| `pathParameters` | `object` | — | Values substituted into matching bare URL placeholders; runtime component/variable templates are resolved before backend substitution. |
| `bodyTemplate` | `string` | — | Request body string with component/variable templates. |
| `authenticationType` | `string` | ✅ | Authentication strategy (see allowed values above). Credentials are never stored here. |
| `responseMapping` | `array` | — | Deprecated legacy action-local mappings. New mappings use top-level `project.bindings`. |
@ -198,15 +198,17 @@ Declares data flow between a source and a target. Required fields: `id`, `source
```json
{
"id": "bind_status_panel",
"source": "variables.lastRunStatus",
"target": "components.statusPanel.message",
"trigger": "onChange"
"source": "actions.action_trigger_workflow.response.body.status",
"target": "components.statusPanel.value",
"trigger": "onSuccess"
}
```
Action-response bindings support `actions.<actionId>.response[.body.<field>]` sources with `onSuccess`. Table selection uses `components.<tableName>.selectedRow` with `onChange`. Component targets are checked for compatible `.value`, Dropdown `.options`, or Table `.rows` properties. A `variables.<name>` target must be declared, but v1.0.0 assigns its response value without runtime type coercion or enforcement.
### `Variable`
A named global or page variable. Required field: `type`. Omitted `scope` means `global` for compatibility; `scope: "page"` requires a valid owning `pageId`.
A named global or page variable. Required field: `type`. Omitted `scope` means `global` for compatibility; `scope: "page"` requires a valid owning `pageId`. Page scope records the intended owner, but v1.0.0 does not enforce that ownership across every template or binding reference.
Allowed `type` values: `string` · `number` · `boolean` · `object` · `array`
@ -290,23 +292,9 @@ ajv validate \
2. The `"$schema"` field at the top of the file points to the schema.
3. VS Code will underline validation errors inline and provide autocomplete.
### In the Backend (future — Step 11)
### In Conductor
The backend will use [`ajv`](https://ajv.js.org/) at runtime to validate project definitions on save:
```ts
import Ajv from 'ajv';
import schema from '../../shared/schemas/conductor-project.schema.json';
const ajv = new Ajv({ strict: true });
const validate = ajv.compile(schema);
function validateProjectJson(doc: unknown): string[] {
const valid = validate(doc);
if (valid) return [];
return (validate.errors ?? []).map(e => `${e.instancePath} ${e.message}`);
}
```
The backend applies this schema plus the semantic rules in [Project Validation](VALIDATION.md) before create, update, save, load acceptance, and publication. The JSON Editor uses the same validation contract before Apply. Validation failures leave the last valid project and stored row unchanged.
> This is documented here for reference. The validation endpoint itself is not part of Step 7.

View File

@ -1,10 +1,21 @@
# Secrets and Authentication Security Model
## Approved MVP policy
## Stored credential policy
Conductor stores credential values server-side in SQLite encrypted with AES-256-GCM. A persistent 32-byte master key is supplied to the backend as `CONDUCTOR_SECRET_KEY`, encoded as base64 or 64 hexadecimal characters. The key is never stored in SQLite, project JSON, frontend state, exports, logs, or source control.
Conductor stores REST credential values in SQLite encrypted with AES-256-GCM. A persistent 32-byte master key is supplied as `CONDUCTOR_SECRET_KEY`, encoded as base64 or 64 hexadecimal characters. The key is never stored in SQLite, project JSON, frontend state, browser responses, execution history, or source control.
Canonical actions will identify credentials by an opaque secret-reference ID. Credential values are never embedded in the canonical project document. Anonymous actions require no secret.
Canonical project actions identify credentials by an opaque `secretReferenceId`. After authorization, the backend resolves the credential while constructing the upstream request. Destination and redirect policy must pass before that request is transmitted; the browser never receives the credential value.
## Access boundaries
- Administrators can create, replace, list, and delete stored-credential metadata through **Actions & Bindings → Secrets**.
- Administrators cannot retrieve an existing credential value; replacement requires the complete new value.
- Users and anonymous visitors cannot list secret metadata or access authoring APIs.
- Public applications may contain only anonymous actions and cannot use stored credentials.
- Restricted published applications may use stored credentials, but the browser submits only runtime values to an action already fixed in the server-owned snapshot.
- Host operators with both the database and encryption key are inside the trusted recovery boundary and could decrypt credentials.
Deletion is blocked while a saved project action refers to the credential. Secret names and authentication types are non-secret metadata, but should still avoid embedding customer or credential values.
## Stored credential shapes
@ -13,23 +24,23 @@ Canonical actions will identify credentials by an opaque secret-reference ID. Cr
- `apiKeyHeader`: header name and API-key value
- `apiKeyQueryParameter`: query-parameter name and API-key value
Secret names and authentication types are non-secret metadata. List and lookup APIs return only ID, name, authentication type, and timestamps. There is no API that returns a stored credential value. Creation and replacement accept credential values but return metadata only.
List and lookup responses contain only ID, name, authentication type, and timestamps.
## Threat assumptions and boundaries
## Key and session lifecycle
- Conductor v0.1.0 is a single-user deployment; accounts, tenant isolation, and RBAC are out of scope.
- TLS termination and host access controls are deployment responsibilities. Credential submission must use HTTPS outside trusted local development.
- SQLite disclosure alone must not reveal plaintext. An attacker holding both the database and master key can decrypt credentials.
- Process or browser compromise, memory inspection, hostile administrators, and compromised destinations are not prevented by encryption at rest.
- Authentication injection and error/log/URL redaction occur server-side. Query API keys require URL sanitization before logging.
- Generate `CONDUCTOR_SECRET_KEY` once with `openssl rand -hex 32` and preserve it across restarts, upgrades, and restores.
- Generate `CONDUCTOR_SESSION_KEY` independently with `openssl rand -hex 32`. It protects sessions; changing it signs everyone out.
- Production startup fails if the encryption key does not encode exactly 32 bytes or the session key contains fewer than 32 bytes.
- Losing or changing `CONDUCTOR_SECRET_KEY` makes existing stored credentials unrecoverable.
- Online key rotation and credential re-encryption are not implemented in v1.0.0.
- Never commit `.env`, paste key values into tickets, or include them in terminal recordings and screenshots.
## Key and lifecycle contract
The public installation procedure creates `.env` with mode `0600`. The backup tool includes that file because the database alone is not a complete recovery set. Treat every backup archive as a credential-bearing secret, keep an off-host copy, and restore the archive as one unit. Do not combine a database with keys from another installation.
- Generate the key outside Conductor and inject it through a Docker secret or environment variable.
- Retain the same key across restarts and back it up separately from SQLite.
- Losing the key makes stored credentials unrecoverable.
- Key rotation requires a deliberate future procedure and is not part of this increment.
- If the key is absent or malformed, anonymous behavior remains available while secret creation, replacement, and resolution fail closed.
- Secret deletion is permanent. Reference-aware deletion safeguards will accompany canonical action references.
## Threat assumptions
Generate a development key with `openssl rand -base64 32`, then set `CONDUCTOR_SECRET_KEY` before starting Docker Compose. Never commit the value.
Encryption at rest protects against disclosure of SQLite alone. It does not protect against compromise of the running backend process, a hostile host administrator, memory inspection, a compromised REST destination, or an attacker who obtains both the database and master key.
Authentication injection, URL sanitization, and error/history redaction occur server-side. Query-string API keys receive the same encrypted storage but remain inherently more likely to be exposed by an upstream service; prefer header-based authentication when the destination supports it.
See [Authorization and Publishing Security](AUTHORIZATION_AND_PUBLISHING_SECURITY.md), [Proxy Security](PROXY_SECURITY.md), and [Production Operations](OPERATIONS.md) for the surrounding trust and recovery model.

View File

@ -1,5 +1,20 @@
# Troubleshooting
## Image pull reports `manifest unknown`
Confirm that the `v1.0.0` Release has been published and that `.env` contains the immutable production tag:
```dotenv
CONDUCTOR_IMAGE=gitea.skeletonworks.online/vwiebe/conductor
CONDUCTOR_VERSION=v1.0.0
```
Do not substitute `latest`. The production release must pull anonymously; if the registry requests a login after publication, report a release-distribution failure rather than adding private credentials to the installation.
## Image pull reports no matching platform
The v1.0.0 production image supports Linux/AMD64 only. Confirm `uname -m` reports `x86_64`. ARM64 is not a supported v1.0.0 target.
## Container exits immediately
Inspect logs. Production intentionally refuses to start when `CONDUCTOR_SECRET_KEY` is not a valid 32-byte base64/hex value or `CONDUCTOR_SESSION_KEY` is shorter than 32 bytes.
@ -14,6 +29,10 @@ curl -v http://127.0.0.1:8080/api/health
Confirm `/data` is writable by UID/GID 10001. Restore tooling resets database ownership to `10001:10001` and mode `0600`.
## Setup or login does not persist in the browser
Production cookies are marked `Secure`. Use the final `https://` hostname, not a plain-HTTP server IP or hostname. The loopback HTTP endpoint exists for host health checks.
## Stored credential no longer works after restore
The restored database and `CONDUCTOR_SECRET_KEY` likely do not match. Restore the complete archive, including its `.env`/`.secrets`. Credential encryption cannot be bypassed or recovered without the original key.

View File

@ -1,46 +1,192 @@
# User Guide
This guide explains how to build and use applications in Conductor. Server installation, TLS, backups, and upgrades belong in the [Installation Guide](INSTALL.md) and [Operations Guide](OPERATIONS.md). Account, credential, and publication administration belong in the [Administrator Guide](ADMIN_GUIDE.md).
## Roles and entry points
- **Admin** users create projects, manage credentials and users, inspect execution history, and publish applications.
- **User** users open restricted published applications and manage their own local password/profile.
- Public applications can be opened without signing in.
| Visitor | What they can do |
|---|---|
| Administrator | Author projects, manage stored credentials, test REST actions, inspect execution history, manage users, and publish applications. |
| User | Sign in, open restricted or public applications from the application catalog, and change their own password. |
| Anonymous visitor | Open public applications by URL. |
A fresh installation creates its first administrator in the browser. Later accounts are managed from **Users**.
There is no public registration page. An administrator creates accounts. Conductor ships with no default username or password.
## Building an application
On a brand-new installation, the first visitor sees **Set up Conductor** instead of the sign-in form. That one-time screen creates the initial administrator: enter a unique username, an optional display name and contact email, and a confirmed password of at least 12 characters. The new administrator is signed in automatically. If the screen is not present, setup has already been completed; ask an existing administrator for an account.
1. Create or load a project in **Visual Editor**.
2. Use **Pages** to add, duplicate, reorder, name, slug, hide, default, or delete pages.
3. Add components from the palette and configure the selected component in the inspector.
4. Define variables, REST actions, credentials, and response bindings in **Actions & Bindings**.
5. Configure Button action/navigation events and page `onLoad`/`onEnter` lifecycle actions.
6. Use **Preview** to exercise the application without changing canonical saved state.
7. Save or update the project.
8. Publish from **Publishing** as public or restricted.
## Sign in and change your password
Public publications may use only anonymous actions. Restricted publications may use backend-held credentials. Publishing creates an immutable snapshot; edit/save and republish to release changes.
Open the HTTPS URL supplied by your administrator and sign in with your username and password. After five failed attempts for the same username and client address within one minute, login is temporarily throttled.
## Variable and component scope
Users can expand **Change my password** below the application catalog. The new password must contain at least 12 characters and differ from the current password. A successful change keeps the current browser signed in and revokes the user's other sessions.
Component names are local to a page. The same name may be reused on different pages. Global variables are available throughout the app; page variables belong to one page. Values persist while navigating in one loaded session and reset on full reload.
Administrators reset passwords from **Users**. Profile fields are administrator-managed in this release.
## Lifecycle behavior
## Administrator workspace
- `onLoad`: first entry to that page during the loaded session.
- `onEnter`: subsequent entry when returning to the page.
Administrators see these areas in the sidebar:
- **Visual Editor** builds pages and components.
- **JSON Editor** edits the same canonical project document directly.
- **Preview** runs the current in-memory project without saving runtime state.
- **Actions & Bindings** defines REST requests, stored-credential references, variables, and response mappings.
- **Execution History** shows recent sanitized REST executions.
- **Publishing** creates and updates runnable application snapshots.
- **Users** manages local accounts and sessions.
The **Projects** sidebar item is a placeholder in v1.0.0. Create, save, and load projects from the toolbar in **Visual Editor** or **JSON Editor**.
## Build a first application
This small workflow creates a page with an input, a button, and a JSON result.
1. Open **Visual Editor** and select **New**.
2. Click the project name in the toolbar and give it a meaningful name.
3. In the page ribbon, set the page name and URL slug. Slugs use lowercase letters, numbers, and single hyphens, such as `lookup`.
4. Click **Text Input**, **Button**, and **JSON Viewer** in the component palette. Move or resize them on the canvas and give each a clear name in **Selection**, such as `itemId`, `lookupButton`, and `resultViewer`.
5. Open **Actions & Bindings**, expand **REST Actions**, and add an action. Choose the HTTP method, enter an absolute `http` or `https` endpoint, and use `{{components.itemId.value}}` in a supported request field when the endpoint needs the entered value.
6. Return to **Visual Editor**, select the button, and assign its click event to the action.
7. In **Actions & Bindings**, add a response binding from `actions.<action-id>.response.body` to `components.resultViewer.value` with trigger `onSuccess`.
8. Open **Preview**, enter a value, and click the button. Resolve any validation errors before continuing.
9. Select **Save**. Later edits use **Update**. The dot beside the project name means there are unsaved changes.
10. Ask an administrator to publish the saved project, or use **Publishing** if you are an administrator.
Use a harmless test API while learning. A Conductor action is a real server-side HTTP request.
## Projects and unsaved changes
- **New** starts a new in-memory document.
- **Save** validates and creates the project in SQLite.
- **Update** validates and replaces the saved project.
- **Load** opens the project picker and loads a saved project.
- Clicking the project name in the toolbar renames it.
New and Load ask before discarding unsaved changes. Failed validation, saving, or loading leaves the last valid in-memory project intact. Preview includes current unsaved edits, but Preview activity never saves component values, responses, loading states, or errors.
## Pages
Use the Visual Editor page ribbon to:
- add, duplicate, reorder, or delete pages;
- change the page name and URL slug;
- choose the default page;
- include or hide a page in automatic navigation; and
- assign page lifecycle actions.
A project always has at least one page. Page slugs must be unique. Hiding a page from navigation is not an access-control rule; anyone allowed to use the application can still open its direct URL.
Lifecycle actions behave as follows:
- `onLoad` runs on the first entry to the page during the current loaded session.
- If a page has no `onLoad` action, `onEnter` is the first-entry fallback.
- `onEnter` runs when the visitor returns to an already visited page.
- A full browser reload starts a new runtime session.
## Components
Click a palette item to add it to the active page. Select a component to edit its name, position, size, visibility, type-specific properties, and basic appearance. Component names must be unique within a page. Project-wide unique names are recommended because request templates and binding paths identify components by name without a page qualifier.
| Component | Main use |
|---|---|
| Label | Static text or a response-bound value. |
| Button | Run one REST action or navigate to another page when clicked. |
| Text Input | Collect one line of text for a request template. |
| Text Area | Collect or display multi-line text. |
| Checkbox | Collect or display a Boolean value. |
| Radio Group | Choose one configured option. |
| Dropdown | Choose one configured option; its option list can be populated by a response binding. |
| Table | Display configured or response-bound rows and expose the selected row at runtime. |
| JSON Viewer | Display formatted configured data or a REST response. |
| Status Panel | Display a value plus loading or error state. |
| Card | Display a titled block of content. |
A button's guided click event runs an action or navigates; it does not do both. Deleting a referenced component displays the references that will be affected before confirmation.
## REST actions and request values
REST actions are project-level and support `GET`, `POST`, `PUT`, `PATCH`, and `DELETE`. Each action defines:
- a stable action ID, name, and optional description;
- an absolute endpoint URL;
- an authentication type and compatible stored-secret reference when required;
- allowed headers, query parameters, and path substitutions; and
- an optional request body for methods that send one.
Use the editor's template suggestions to place runtime values in supported request fields:
```text
{{components.itemId.value}}
{{variables.environment}}
```
Component values resolve from the page that invoked the action. Variables resolve by name. Treat a page-scoped variable as belonging only to its declared page; v1.0.0 does not yet enforce that ownership when resolving every runtime reference. Do not put passwords, tokens, or API keys into templates, headers, URLs, or project JSON; select a compatible stored secret instead.
**Test Action** runs the current action configuration through the backend proxy. It is useful for static requests. It does not inject interactive Preview values, so exercise template-driven requests from **Preview**.
Conductor blocks private and internal destinations unless the server operator has approved the exact origin. See [Proxy Security](PROXY_SECURITY.md) for allowed headers, limits, redirects, and error behavior.
## Stored credentials
Administrators create credentials in **Actions & Bindings → Secrets**. Supported shapes are Basic authentication, Bearer token, API-key header, and API-key query parameter.
Credential values are encrypted server-side and are never displayed again after submission. Projects store only opaque references. Replacing a value requires entering the new credential fields once; deleting a credential is blocked while a saved project action references it. More detail is in the [Administrator Guide](ADMIN_GUIDE.md#manage-stored-credentials) and [Secrets Security Model](SECRETS.md).
## Variables and response bindings
Variables have a type (`string`, `number`, `boolean`, `object`, or `array`), an optional default, and either global or page scope. Keep page-scoped variables on their declared page. Runtime values survive navigation within one loaded session and reset on full reload. They are not written back to the project document.
Response bindings run after a successful action and use ordinary dot-separated object paths, not JSONPath. Common sources are:
```text
actions.<action-id>.response
actions.<action-id>.response.body
actions.<action-id>.response.body.<field>
```
Supported targets are:
| Target | Compatible destination |
|---|---|
| `components.<name>.value` | Label, Text Area, Checkbox, Radio Group, JSON Viewer, or Status Panel |
| `components.<name>.options` | Dropdown; response must be an array of strings or string `{ "label": ..., "value": ... }` objects |
| `components.<name>.rows` | Table; response must be an array of objects |
| `variables.<name>` | A declared runtime variable; the response value is assigned without coercion or a runtime type check |
Use `onSuccess` for action-response bindings. Table selection uses `components.<table-name>.selectedRow` with `onChange`. The guided response-binding editor creates action-response bindings only; use the **JSON Editor** to add a Table-selection binding, and keep the Table name project-wide unique. Wildcards, filters, transforms, action chains, and arbitrary reactive graphs are not executed in v1.0.0.
## Preview and validation
Preview is a read-only runtime view of the current canonical project. It can change ephemeral component and variable values while the Preview remains loaded, but it does not alter or save the authored defaults.
Validation summaries appear in the Visual Editor, Actions & Bindings, JSON Editor, and Preview. Errors block Apply, Save, and Publish. Warnings usually identify compatibility fields that remain readable but are not executed. Fix the named path or reference and validate again.
## JSON Editor
The JSON Editor edits the same canonical document as the Visual Editor. Validate and apply before saving. Invalid JSON or semantic references do not replace the last valid in-memory document.
The JSON Editor edits the same project document as the Visual Editor.
## Credentials
1. Make changes in the text area.
2. Select **Apply** to parse and validate them.
3. Return to the Visual Editor or Preview to inspect the result.
4. Select **Save** or **Update** to persist it.
Credential values are submitted to encrypted server-side storage and are never displayed again. Projects contain opaque secret references, not values. Replacing a credential requires entering the new value twice where applicable.
**Revert** discards the JSON Editor's local draft and returns to the current in-memory project. Invalid JSON or semantic references never replace the last valid project. The canonical format is documented in [Project Schema](SCHEMA.md); prefer the visual editors for shapes they support.
## Published URLs
## Published applications
- `/apps/<app-slug>` opens the default page.
- `/apps/<app-slug>/<page-slug>` is a refreshable page deep link.
Publishing creates an immutable snapshot of a saved project:
Hiding a page removes it from automatic navigation; it is not an authorization rule.
- `/apps/<app-slug>` opens its default page.
- `/apps/<app-slug>/<page-slug>` opens a refreshable deep link.
- Public applications are available anonymously and may contain only anonymous REST actions.
- Restricted applications are available to any enabled signed-in user and may use stored credentials.
Saving the source project does not change the live snapshot. Use **Republish** to release the current saved version. **Unpublish** makes the URL unavailable without deleting the source project. See the [Administrator Guide](ADMIN_GUIDE.md#publish-and-withdraw-applications).
## Troubleshooting and limitations
- If an action is blocked, read its safe error code and ask the server operator before requesting an internal-origin exception.
- If a deep link returns a proxy 404, the reverse proxy is not forwarding all paths to Conductor.
- If an old interface remains after an upgrade, perform a hard refresh.
- If Apply, Save, or Publish fails, correct the validation path shown in the interface; the last valid project remains intact.
See [Troubleshooting](TROUBLESHOOTING.md) for remedies and [Known Limitations](KNOWN_LIMITATIONS.md) for the full v1.0.0 boundary.

View File

@ -6,7 +6,7 @@ Conductor uses `shared/schemas/conductor-project.schema.json` plus backend seman
- This release accepts exactly `schemaVersion: "0.1.0"`.
- Other versions fail with `SCHEMA_VERSION_UNSUPPORTED`; Conductor does not guess, coerce, or migrate them.
- Invalid stored JSON is left untouched and returned as `STORED_PROJECT_INVALID` when loaded. There is no automatic v0.1.0 migration.
- Invalid stored JSON is left untouched and returned as `STORED_PROJECT_INVALID` when loaded. There is no automatic project-schema migration.
- Missing properties remain missing and explicit JSON values—including `null`, empty arrays, and empty objects—are preserved. Validation does not apply schema defaults or mutate documents.
## Result contract
@ -32,7 +32,7 @@ No database write occurs until parsing, schema validation, and semantic validati
Blocking checks cover:
- unique page, action, binding, and project-wide component identities/names;
- unique page, action, and binding identities/names; project-wide component IDs; and component names within each page;
- supported page/component events and existing action references;
- existing action, component, variable, binding, and default-page references;
- runtime-supported action-response paths and Table-selection sources, triggers, and component target properties;
@ -43,10 +43,10 @@ Blocking checks cover:
Path parameters follow one contract: frontend runtime interpolation resolves `{{components.<name>.value}}` and `{{variables.<name>}}` inside `pathParameters` values; the backend then substitutes those rendered values into bare URL placeholders such as `{{itemId}}`.
Table selection uses the canonical component binding shape `components.<tableName>.selectedRow``components.<displayName>.value` with trigger `onChange`. The source must resolve to exactly one Table and the target must support runtime `value`. Selecting a row updates only ephemeral Preview state; neither the selected row nor the display value is persisted.
Table selection uses the canonical component binding shape `components.<tableName>.selectedRow``components.<displayName>.value` with trigger `onChange`. Use a project-wide unique Table name: v1.0.0 validation does not diagnose same-named source Tables on different pages. The target must resolve uniquely and support runtime `value`. Selecting a row updates only ephemeral Preview state; neither the selected row nor the display value is persisted.
## UI and recovery
Visual Editor, Actions & Bindings, JSON Editor, and Preview display the shared result. A validation/network failure leaves canonical state and JSON Editor draft text unchanged. Save remains dirty after failure. Loading an invalid stored document leaves the currently open project intact. New and Load ask for confirmation before discarding unsaved edits.
Project deletion remains backend-only for v0.1.0. A dedicated Projects screen and deletion control are deferred because project browsing is not yet an implemented MVP surface; the existing API continues to require an explicit project ID.
Project deletion remains backend-only for v1.0.0. A dedicated Projects screen and deletion control are deferred because project browsing is not yet an implemented MVP surface; the existing API continues to require an explicit project ID.

View File

@ -15,12 +15,12 @@ New response mappings are top-level `project.bindings`. The legacy `action.respo
## Action execution
Actions are project-level and reusable. A Button `onClick`, Dropdown `onChange` where supported, or page lifecycle event selects an `actionId`. A Button event may instead contain `navigateToPageId`; navigation is not represented as a REST action.
Actions are project-level and reusable. A Button `onClick` or page lifecycle event selects an `actionId`. A Button event may instead contain `navigateToPageId`; navigation is not represented as a REST action. Table row selection drives `onChange` data bindings rather than executing an action directly.
Before execution, request fields interpolate:
- `{{components.<name>.value}}` against components on the invoking page only.
- `{{variables.<name>}}` against global variables or page variables owned by the invoking page.
- `{{variables.<name>}}` against the project's runtime-variable map. Page scope records intended ownership, but v1.0.0 does not enforce that ownership across every runtime reference; authors must keep page variables on their declared page.
Credential-backed authentication is resolved by the backend through opaque `secretReferenceId`. Browser clients never supply authoritative URLs, authentication modes, actions, or secret values for published execution.
@ -45,7 +45,7 @@ Supported action-response targets are validated against component type/property
- `components.<tableName>.rows`
- `variables.<name>`
Component names are page-local. Response bindings execute in the invoking page context and may update components on that page, global variables, and page variables owned by that page. Cross-page component/page-variable writes are prohibited.
Component names are validated within a page, but binding paths do not contain a page ID. The current runtime requires a component target name to resolve unambiguously across the project and skips a binding when several pages reuse that name. A same-named Table on multiple pages can also activate the same selection binding. Use project-wide unique component names. Keep page-variable targets on their owning page; cross-page response flows are not a supported authoring pattern, although that variable-scope boundary is not fully diagnosed or enforced in v1.0.0.
## Triggers
@ -63,6 +63,7 @@ Actions expose loading, success, upstream failure, network/policy failure, and m
## Lifecycle
- Page `onLoad` runs on the first entry to that page during one loaded runtime session.
- If no `onLoad` event is configured, `onEnter` is the first-entry fallback.
- Page `onEnter` runs when returning to a previously visited page.
- Reopening/reloading the runtime begins a fresh session.
@ -74,7 +75,7 @@ Validation rejects or warns about:
- unsupported trigger/source/target combinations;
- duplicate page/component identities in their required scopes;
- malformed templates and unsupported component template properties;
- page-variable ownership violations and cross-page references;
- a page-scoped variable whose declared owner page does not exist;
- incompatible response target properties;
- deprecated `action.responseMapping` and inert `inputMap` compatibility fields.

View File

@ -1,12 +1,12 @@
{
"name": "conductor-frontend",
"version": "0.1.0",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "conductor-frontend",
"version": "0.1.0",
"version": "1.0.0",
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",

View File

@ -1,6 +1,6 @@
{
"name": "conductor-frontend",
"version": "0.1.0",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "^18.3.1",

View File

@ -30,7 +30,7 @@ test('shows compatibility warnings without treating them as blocking errors', ()
validation: {
valid: true,
errors: [],
warnings: [{ code: 'BINDING_TRANSFORM_DEFERRED', path: '/project/bindings/0/transform', message: 'Binding transforms are modeled but are not executed in v0.1.0.', severity: 'warning' }],
warnings: [{ code: 'BINDING_TRANSFORM_DEFERRED', path: '/project/bindings/0/transform', message: 'Binding transforms are modeled but are not executed in this release.', severity: 'warning' }],
},
});
const markup = renderToStaticMarkup(<ValidationSummary />);

View File

@ -17,7 +17,7 @@ const requireText = (file, text, label) => {
};
requireText('MVP_SCOPE.md', 'The initial MVP has no AI dependency.', 'approved no-AI boundary');
requireText('docs/REQUIREMENTS.md', '`MVP_SCOPE.md` is the approved v0.1.0 release boundary.', 'scope authority');
requireText('docs/REQUIREMENTS.md', '`MVP_SCOPE.md` is the approved MVP and v1.0.0 release boundary.', 'scope authority');
requireText('docs/REQUIREMENTS.md', '## 12. Resolved MVP Decisions', 'resolved-decision section');
requireText('docs/MVP_TRACEABILITY.md', '## Release-critical requirements', 'requirements matrix');
requireText('docs/MVP_TRACEABILITY.md', '## Explicit post-MVP classifications', 'post-MVP classification');

View File

@ -4,7 +4,7 @@ set -euo pipefail
IMAGE="${IMAGE:-gitea.skeletonworks.online/vwiebe/conductor}"
VERSION="${VERSION:-}"
PUSH=false
PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}"
PLATFORMS="${PLATFORMS:-linux/amd64}"
while [[ $# -gt 0 ]]; do
case "$1" in