# Security and Operations ## Scope and Assurance Status: retained source evidence and chosen initial operational specification, with bounded runtime evidence current to 2026-09-30. Final D01-D10 are settled; operational controls are only partially implemented and the platform is not security-certified. See [implementation status](status.md) for the scope actually verified. This document translates [identity and governance](../architecture/identity-and-governance.md) into implementation and operational checks; it does not define identity or policy semantics. Current source observations and focused component tests are not a security certification, penetration test, deployment verification or full new-platform acceptance. [Implementation architecture](architecture.md) specifies the initial runtime and database mechanisms; [identity and governance](../architecture/identity-and-governance.md) defines authority. Hosting configuration must satisfy those contracts, not reopen them. The old organization/client/admin hierarchy is not the new authorization model. Preserve isolation and explicit authority, not those tables or roles. Documentation workflow and lineage belong to [documentation governance](../governance/documentation.md) and the [source map](../governance/source-map.md). ## Current Configuration Contract This section records the former runtime's configuration as historical evidence only. New-runtime mechanisms below must be implemented and checked before operational use. The removed legacy configuration preferred a nonempty process environment value, then a string value from an external PHP array, then the caller's default. The external array is cached for that process/request context. The application does not itself load dotenv files; no environment-example file is promised here. Do not inspect or print live secrets to verify this contract; inspect source and use isolated nonsecret fixtures. | Name | Observed purpose and default | | --- | --- | | `APP_CONFIG_FILE` | Overrides the external secrets file path through the process environment | | `DB_DSN` | Optional explicit PDO DSN; must start with `mysql:` in the old runtime | | `DB_HOST` | Host when constructing the DSN; no application host default | | `DB_PORT` | Optional port segment; omission leaves port selection to the driver, not a hard-coded application value | | `DB_NAME` | Database name when constructing the DSN | | `DB_USER`, `DB_PASS` | Connection credentials, also used with an explicit DSN | | `DB_CHARSET` | Defaults to `utf8mb4` when constructing the DSN | | `APP_ENCRYPTION_KEY` | 64 hexadecimal characters representing 32 key bytes for the current crypto helper | | `APP_ENCRYPTION_KEY_VERSION` | WordPress credential metadata label, default `v1`; not implemented multi-key decryption | | `GROQ_API_KEY` | Optional credential enabling the existing WordPress generation request | | `GROQ_MODEL` | Defaults to `llama-3.3-70b-versatile` | | `GROQ_API_URL` | Defaults to `https://api.groq.com/openai/v1/chat/completions` | The removed legacy database helper constructed `mysql:host=[;port=];dbname=;charset=` when `DB_DSN` was absent. An explicit DSN supplies its own charset/port; the separate variables are not appended to it. Current PDO options are exception errors, associative fetches and native prepares; the target uses PDO with the `pdo_mysql` driver against MariaDB 10.5.26/InnoDB. The `mysql:` PDO DSN and driver name are the expected PDO mechanism for MariaDB; other database drivers are rejected. This is the initial production compatibility contract, not a claim of portability to other database engines. Without `GROQ_API_KEY`, generation is unavailable; manual building, local saves and remote draft creation have no AI-provider dependency, though their other prerequisites still apply. Groq is an optional old adapter detail, not a provider-specific core requirement; the [AI owner](../architecture/ai.md) governs the no-AI guarantee. ## External Secrets and Encryption The observed default configuration path is one directory above the project root: `.idiosyncrasy-secrets.php` via `dirname(__DIR__, 3)` in Config. The documented Plesk example is `/var/www/vhosts/idiosyncrasy.co.uk/.idiosyncrasy-secrets.php`, outside the platform document root. This is a known deployment path, not confirmation that a file exists or was read, and not a required future host. Where PHP-FPM environment variables are unavailable, an operator can provide the external PHP array at an approved path and restrict access to the subscription owner/runtime identity. Because it is executed with PHP `require`, the secrets file must be trusted configuration, never user-uploaded content. Keep credentials, encryption keys, provider tokens, runtime uploads and deployment credential files out of source control and public deployment bundles. ## Target Release and Local Execution Controls The operator-only `bin/reset-principal-password.php` boundary is a staging recovery mechanism for an already-confirmed User (legacy Type name Principal) when no interactive password-reset channel is available. It requires `--database=target`, `--confirm-target=staging`, `IDY_ALLOW_TARGET_PROVISIONING=1`, the resolved staging database configuration and a password supplied through `IDY_OPERATOR_PASSWORD`; the password is never a command-line argument or release value. It validates the User's active status, updates the Argon2id credential through `PrincipalCredentialResetService`, and records a `principal.password_reset` security-audit event in the same transaction. It is not an HTTP route, does not bypass confirmation, and must not be used for production or by editing credential tables directly. The operator-only `bin/reconcile-foundation.php` boundary is a staging-only forward reconciliation for the approved IDY-003 Business Type descriptor. It requires the same explicit target safeguards and authenticated User, appends the descriptor as object revision 2 through the generic repository, records `foundation_reconciliations`, and leaves the immutable original `genesis_runs` record untouched. It accepts only the repository's approved current manifest and the supported predecessor descriptor; it is idempotent and fails closed for any other foundation drift. The reviewed target release definition is the authority for target composition. Release tooling resolves only its approved paths, rejects traversal, absolute paths and links, and emits deterministic SHA-256 manifest evidence. The current source boundary includes the persisted Definition validator, governed publication Operation handler, Capability Application handler and persisted projector, server-resolved Operation input reader, exact Operation-identity Action authorization, no-network `send_email` Provider/handler, core-object Presentation provisioning, shared configuration runtime-ID resolver and holistic view, immutable runtime vocabulary descriptors, definition-driven initialization classes, target wordmarks and User confirmation-delivery classes (legacy class names use Principal); provisioning-only publisher installation, Genesis and platform-opening materials remain outside the public runtime package. The retired historical staging snapshot is not part of current release evidence. A package is eligible for deployment only when its canonical manifest carries GitHub authority, repository, exact full commit SHA and non-secret build identity. The internal [StagingProvisioningPackage](../../app/Release/StagingProvisioningPackage.php) is a distinct operator-only artifact bounded by its own manifest and required provisioning paths. It includes required provisioning runtime classes, including the publisher authority installer, local runtime environment loader and no-network Communication handlers; it is not the public target release package and is not published by the GitHub deployment workflow. Current package-test and read-only target-check evidence is recorded in [implementation status](status.md#target-release-foundation-evidence). Protected CLI provisioning commands use the process environment as their authoritative runtime configuration. `bin/provision-target.php` now loads only an existing local `.env.local` file through the allowlisted `LocalRuntimeEnvironment` helper when a value is not already present in the process environment. It loads only the target database, staging database-name, target runtime and Definition-publisher setting names; it does not print, persist or override explicit process values. The file remains local operator configuration and is never packaged or used by the web runtime. On a STAGING operator workstation, the protected command can therefore use the existing local configuration without placing credentials in command-line arguments. The command still enforces the explicit staging database identity and all existing provisioning safeguards. After local package verification, one recursive SCP operation transfers the manifest-bound public package and two control files into the release-specific non-active `.releases/-staging` path below the documented application root. The verified public release is installed before the existing `/health` check. `bin/staging-deploy.sh` re-verifies the downloaded package, requires the manifest-bound package identity and `target/.htaccess`, uses `sshpass -d` to provide the staging password to OpenSSH and SCP without placing it in command arguments, and emits only non-secret repository, commit, release, digest and URL evidence. `bin/target-check.ps1` is read-only and does not connect to a database. `bin/target-local.ps1` requires the pinned PHP runtime, reads the local connection file outside the repository, accepts loopback hosts only, rejects production-looking database names, clears legacy database variables and uses `var/target-sessions-local`. These controls are local-development safeguards, not production deployment or hosting certification. Production activation, credential provisioning, migrations, backups, ingress checks and rollback remain unverified operational work. `bin/target-release.ps1` reports local preflight, GitHub-bound package verification, production connection, staging/upload, remote verification, blocked activation and final result as explicit operator-visible phases. It consumes an existing package and never silently builds from the local working tree. It reads only the existing `.deploy/idiosyncrasy-production.json` metadata and an external SSH identity path. It supports non-interactive OpenSSH key authentication and an operator-controlled native interactive password fallback (`Auto`, `Key` or `Password` mode); the password is never captured, stored, passed as a command-line argument, logged, or packaged. Strict host-key verification remains mandatory. After local package verification, one recursive SCP operation transfers the manifest-bound public package and two control files into the release-specific non-active `.releases/-staging` path below the documented application root. Remote verification then compares the exact reviewed manifest paths, byte counts, SHA-256 values and GitHub provenance. Native SSH/SCP failures report the executable, non-secret operation context, exit code, captured output and PowerShell exception details when present, without printing command arguments or password material. Failed staging remains identifiable and the active tree and `var/target-sessions` are not removed or replaced. `bin/target-activate.ps1 -ReleaseId -ArtifactDigest -CommitSha ` is the separate explicit activation operator for an already-uploaded release. It does not rebuild or upload. Its remote preflight now requires matching release ID/artifact digest plus GitHub repository and exact commit provenance before the existing filesystem switch could be attempted. The activation unit is the complete release root under `.releases/-staging`; the fixed Plesk document root remains `target`, which is switched to a symlink targeting that release's `target/` directory so relative `../bootstrap`, `app` and `resources` resolution stays within the same release root. Before switching, the existing real `target` directory is moved intact into a release-specific previous-live rollback directory. A lock prevents concurrent activation; any pointer, identity or HTTP `/register` failure restores the previous target automatically. On success, the previous target remains retained for rollback. This operation performs no database, session, migration, provisioning, Genesis, platform-opening, environment-variable, Plesk or document-root configuration changes. The ordinary release command remains non-activating and refuses migrations, provisioning, Genesis, platform opening, schema changes, data mutation, credential creation and Plesk configuration changes. `target-activate.ps1` is the only activation path; it requires the release-specific staging prerequisite and a successful post-switch filesystem and HTTP `/register` check before reporting success. It is not a substitute for remote manifest verification. The former `bin/target-upload-direct.ps1` path has been removed. A `push` to `main` runs the build and provenance job, then the protected `deploy-staging` job invokes `bin/staging-deploy.sh` automatically for application package installation and health verification only. After that workflow completes successfully for a `main` push, the protected `staging-presentation-profile-migration.yml` workflow is invoked by `workflow_run` for the same commit and reconciles the version-controlled Presentation profile. A manual `workflow_dispatch` remains available for non-deploying build and package diagnostics and for an explicitly selected Presentation migration. The helper uses only `STAGING_SSH_HOST`, `STAGING_SSH_PORT`, `STAGING_SSH_USER`, `STAGING_SSH_PASSWORD`, `STAGING_REMOTE_ROOT` and `STAGING_URL` for transport, install and health verification. It receives no staging database credentials and does not run reset, migration, Genesis, platform opening or provisioning; those operations are internal-script-only and must be explicitly authorized outside GitHub Actions. The verified manifest-bound public release is installed before the existing `/health` check. The job does not use production credentials or a production database path. The push workflow builds and deploys the exact artifact from its triggering `github.sha`; it does not select an arbitrary latest artifact or consume an artifact from another run. The automatic Presentation migration checks the completed upstream workflow conclusion, push event, `main` branch and same-repository identity before running. It checks out the upstream workflow's exact `head_sha`, not the migration workflow's default-branch tip. The migration continues to use the protected SSH route and the existing `extend-business-presentation.php` command. Its Presentation AuthorityGrant ID remains an explicit allowlisted target, while the command reads the current grant version immediately before any governed update and supplies that observed version as the optimistic expected version. This removes stale manually copied version inputs without weakening CommandHandler validation, authority, transaction or provenance checks. Development Staging v1 deliberately uses password SSH with host-key verification disabled through `StrictHostKeyChecking=no` and `UserKnownHostsFile=/dev/null`, solely because the Development Staging v1 requirement is username/password authentication without a pre-populated host-key file. This staging-only transport is not the production deployment transport and must not be inherited by production operations. `bin/staging-deploy.sh` re-verifies the downloaded package, requires the manifest-bound package identity and `target/.htaccess`, uses `sshpass -d` to provide the staging password to OpenSSH and SCP without placing it in command arguments, and emits only non-secret repository, commit, release, digest and URL evidence. It uploads the public package to a remote temporary directory, installs it, and performs one HTTPS `/health` check. It does not receive or create database credential files and does not perform reset, migration, provisioning, Genesis or platform opening. The current Development Staging v1 path does not perform activation, symlink switching, rollback choreography, capability probing, remote manifest reconstruction, root smoke checks, or session-directory changes. Installation or health failures return a nonzero result and trigger temporary local cleanup. ### Staging provisioning contract STAGING uses `php bin/provision-target.php --database=staging` from the internal staging provisioning artifact. The operator must set `IDY_TARGET_DB_HOST`, `IDY_TARGET_DB_PORT`, `IDY_TARGET_DB_NAME`, `IDY_TARGET_DB_USER` and `IDY_TARGET_DB_PASS` through the internal execution environment. `IDY_STAGING_DB_NAME` is optional when the configured target database name is itself used as the STAGING identity; when supplied, it must match that name. The resulting identity must be safe, must not equal `idio2plat`, and must not contain a production/live identity token. The command verifies the selected PDO database, requires it to be empty, applies migrations, runs foundation-only Genesis, installs the approved vocabulary prerequisites and applies the immutable platform-opening release/effect mapping. It never copies production data or credentials and creates no human User, Business or continuing authority. Production provisioning is deferred for the current development phase and has no active selector in this command. The generic target runtime and production identity guard remain internal safety abstractions for future work. The STAGING provisioning artifact is separate from the public runtime package, contains no secrets and is used only by internal scripting. `bin/reset-staging-database.php --database=staging` is the dedicated reset boundary for a disposable staging rebuild. It is CLI-only and requires explicit staging context, explicit reset confirmation, the staging selector, matching `IDY_TARGET_DB_NAME` and `IDY_STAGING_DB_NAME`, and a non-production staging identity. It obtains reset authority only from the separately named `IDY_STAGING_RESET_DB_HOST`, `IDY_STAGING_RESET_DB_PORT`, `IDY_STAGING_RESET_DB_USER` and `IDY_STAGING_RESET_DB_PASS` settings. The reset endpoint must match the configured staging database host and port; the reset user may be the same as the staging runtime/provisioning user under the agreed single-user staging model. Missing capability, mismatched identity or failed recreated-database verification stops the operation before it reports success. These settings must be supplied through the protected internal execution environment; they are not part of the GitHub deployment workflow, and no credential values are present in the repository. The 2026-09-19 activation/staging investigation confirmed that the rotated local identity file is present and resolves to the documented host, but the host still rejects non-interactive SSH authentication with `Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)` before any remote command. This is an infrastructure authorization failure, not evidence that symlink or rename activation is safe. Do not enable activation until the deployment account's accepted authentication mechanism is restored and the remote capability probe is completed without touching the active release or persistent state. The removed legacy crypto helper used OpenSSL AES-256-GCM. It creates a random 12-byte IV and encodes `IV || 16-byte authentication tag || ciphertext` using Base64. Decryption checks encoding/length and the authentication result; there is no embedded key identifier or algorithm-version envelope. Both WordPress application passwords and TOTP secrets use this helper. `APP_ENCRYPTION_KEY_VERSION` is exposed by the WordPress service as metadata; Crypto does not select historical keys using it. Simply changing the key can make stored secrets unreadable. Define rotation, revocation, recovery and key custody before operational use. Keep key material outside MySQL, outside the web root and outside source control; manage its backup separately from database backups. Libsodium `sodium_crypto_secretbox` was a proposed alternative, not the implementation. Any cipher/key-format change requires separate approval, threat analysis, explicit format/version handling and verification; these docs do not implement it or require legacy-data compatibility. Credential plaintext should exist only where needed in request memory, never in markup, logs, exception messages, discovery output or AI prompts. Review the actual error paths for redaction: a stated policy alone does not prove every existing exception is safe. ## Authentication and Session Controls The removed legacy security helper set session cookies with `HttpOnly`, `SameSite=Strict`, path `/`, session lifetime and conditional `Secure`. HTTPS detection uses the server HTTPS flag or `X-Forwarded-Proto`; proxy-header trust must be verified at the deployment boundary. Do not accept arbitrary forwarded headers from untrusted callers. Verify secure-cookie behavior on the real ingress topology. The removed legacy authentication controller verified password hashes, used a dummy hash for unknown users, regenerated the session ID on successful password authentication and gated MFA completion. The old login and MFA paths lock an existing account after five failed attempts for 900 seconds; this is not general distributed brute-force protection. The removed legacy profile controller hashed replacement passwords with bcrypt and required at least 14 characters. Reauthentication, confirmation, password/session revocation and account recovery behavior require separate review; a visible password form does not establish those guarantees. The removed legacy TOTP helper implemented six-digit SHA-1 TOTP with 30-second periods and a default plus/minus-one-step verification window. The removed legacy two-factor controller stored the TOTP secret encrypted, generated eight recovery codes, stored their password hashes and marked a matching code used. Enrollment and pending verification restrict navigation through the front controller; this code does not decide future enrollment policy or mandate removal of PHP sessions. Verify expired challenges, secret exposure during enrollment, replay, rate limiting, recovery-code atomic consumption and concurrent enrollment/verification before relying on MFA assurance. ## Request and Data Boundaries - Verify a CSRF token server-side for every state-changing browser request, including login/logout, uploads and AJAX mutations. - The current helper generates 32 random bytes represented as hexadecimal and compares tokens using `hash_equals`; token creation does not enforce protection on its own. - Resolve user and permitted scope server-side. Apply tenant isolation to reads, writes, relationship endpoints, search, files, jobs and integration operations. - Preserve the principle of organization/client scoping in old paths only as historical evidence; do not equate a selected business object with a future tenant. - Use parameterized queries and approved structural allowlists; error responses must not expose raw database exceptions. - Recheck authorization at action time, including approval-dependent, automated and AI-assisted actions. Browser state is not authority. - Apply bounded request sizes, rate limits and timeouts at relevant boundaries; the existing generation limiter is not proof of platform-wide coverage. - Audit actor, scope, action, target, time and result without secrets; canonical history semantics remain in [time and events](../architecture/time-and-events.md). ## Uploads and Safe Rendering Escape untrusted text for its output context; use a designated sanitizer for intentionally rich content rather than treating all strings as trusted HTML. The removed legacy sanitizer removed selected dangerous HTML elements, event-handler attributes and selected unsafe URL schemes. It is not a complete Gutenberg schema validator or proof that every HTML/CSS/vector attack is covered. The removed legacy SVG sanitizer was used by Brand uploads; any future sanitizer needs its own allowlist and adversarial fixtures. The old Brand upload handler permits JPEG, PNG, GIF, WebP and sanitized SVG, checks server-detected MIME and uploaded-file status, and limits files to 5 MiB. It generates random names and removes a new file after write/database failure; replacement cleanup and storage authorization still need review. Profile avatars also have a 5 MiB limit and server MIME checks, but only raster formats; naming/storage/cleanup differ from Brand. Do not silently promote either upload handler into a general file service or treat a guessed public URL as an access-control mechanism. New storage needs nonexecutable upload locations, authorized reads where required, safe filenames, content/disposition headers and lifecycle cleanup. Test active SVG, polyglots, malformed files, path traversal, oversize requests, mismatched MIME and unauthorized replacement/deletion. User profile images follow the same protected media boundary. Store only an addressable Media/Asset reference on the User object (legacy Type name Principal); keep bytes outside the public document root, generate storage names server-side, validate detected type and size, and serve only an authorized safe rendition. Replacement/removal must clean up unreferenced bytes without deleting a still-referenced asset. Image metadata and access checks must not disclose storage paths, credentials or unrelated Business data. The existing legacy avatar handler is evidence to review, not a compliant new-platform implementation. Current response headers include `nosniff`, frame denial, a referrer policy, permissions restrictions and CSP. The CSP still permits inline scripts/styles and named CDNs; header presence is not complete XSS protection. HSTS is conditional on the server HTTPS flag, so test HTTPS/proxy behavior and required external assets instead of claiming blanket coverage. ## Old-Schema Setup The removed legacy setup command was CLI-only and executed the removed old schema. Its former invocation was `php bin/setup.php`, from a trusted shell for a deliberately approved new, empty OLD-APPLICATION database only. It is not a new-platform bootstrap, upgrade runner, migration scheme, test fixture reset or safe command against an arbitrary configured database. The script does not establish that an existing database is empty; the operator must confirm the target before execution. No setup or database command is part of this documentation change. The removed initial-admin and password-reset scripts were old operational utilities, not specifications for new identity provisioning. ## Deployment and Recovery Use the [chosen PHP/MariaDB runtime](architecture.md#initial-runtime-structure) and verify required extensions, ingress, storage permissions, backups and service management before release. This is implementation verification, not another D07 approval gate. Use least-privilege database and remote credentials; verify TLS, web-root exclusions and environment availability to both web and any future worker process. On Plesk/Apache, verify directory-index precedence: a host's placeholder `index.html` can shadow the target [index.php](../../target/index.php). Authorization-header forwarding may be needed for WordPress application passwords; Apache `CGIPassAuth` depends on host configuration and can cause site-wide failures when disallowed. Have the site operator validate an appropriate rewrite/server configuration on a controlled target; do not prescribe an untested global hosting edit. Restrict outbound/inbound integration access where operationally feasible, including known Idiosyncrasy egress IPs on a WordPress site where appropriate. Document database/blob backup retention, independent key custody, restore authorization and restoration drills; a backup without recoverable keys may be unusable. Record failure correlation, health checks, sanitized error logs and incident ownership without copying secret values into support evidence. There is no general worker/module runtime to deploy or monitor today; worker claiming, retries, health, shutdown and failed-work handling depend on [Workflows and automation](../architecture/workflows-and-automation.md). ## Verification Before Release Use isolated fixtures for session/CSRF failures, cross-scope access, encryption tampering, missing keys, recovery-code reuse, uploads and sanitization. For WordPress, test HTTPS enforcement, private/reserved addresses, DNS changes, IPv6, redirects, timeouts and credential redaction; see [WordPress security](wordpress.md#security-and-outbound-requests). Record checks, environment, date and limitations in [status](status.md). A focused PHPUnit suite is available through `bin/run-tests.ps1`; it refreshes its disposable database from staging, so staging remains authoritative and read-only during normal verification. The [roadmap](../product/roadmap.md) fixes the first milestone and Spearmint scenario. Live WordPress, provider AI and a broad connector estate are not first-milestone prerequisites. ## Initial Runtime Controls **Settled semantic contract:** authoritative identity/context, permission and Policy enforcement, coherent history and explicit recovery. **Chosen implementation mechanisms:** the bounded controls below. **Current status:** this is the operational baseline, not per-control evidence; some bounded controls are implemented, while broader controls remain specified, unverified or not security-certified. See [implementation status](status.md). - Require HTTPS for non-loopback use; only trust forwarded headers from explicitly configured reverse proxies. Isolate the public entry point/assets from application source, configuration, uploads, manifests and logs. - Use server-side sessions with Secure, HttpOnly and SameSite=Strict cookies in HTTPS deployments; regenerate the session ID after login, invalidate it on logout, enforce a 30-minute idle timeout and eight-hour maximum lifetime. These are initial operational parameters, not architecture-level constants. - Hash passwords with the approved password API and keep credential material separate from generic object reads/exports. Registration must normalize and uniquely bind the approved identity association, create a pending User and store only protected credential material and a protected confirmation-challenge verifier. Confirmation challenges are purpose-bound, User-bound, expiring and single-use; raw challenge material must not enter generic objects, logs or evidence. Reject replay, mismatch and expiry without changing authority, apply identity/source rate limits and serialize concurrent confirmation so at most one attempt issues onboarding authority. Generic authentication errors, dummy verification, credential secrecy, CSRF protection, revocation and durable security/audit evidence remain required. No provider-specific identity mechanism is implied. - Rate-limit by identity and source address with atomic durable counters; initially delay/block further login attempts for 15 minutes after five failures within 15 minutes. Do not reuse the old count-then-insert limiter as proof of concurrent enforcement. Record security attempts without passwords or tokens. After successful CSRF validation, every login attempt entering authentication participates in the existing source-address accounting, including malformed or noncanonical identity input. Identity-specific accounting applies only when a canonical User UUID is available; malformed input must never create, access or mutate an identity bucket. Canonical unknown UUIDs receive identity and source accounting, while valid-but-unconfirmed noncanonical identities receive source-only accounting. No second limiter or bucket type is introduced. - Require CSRF protection for login/logout and all state-changing browser submissions, prepared SQL and escaped output. Re-resolve durable membership/authority at request and commit boundaries. The first demo only supports password-assurance operations; an operation requiring stronger authentication is refused until its assurance mechanism is implemented, not silently downgraded. - Restrict the runtime database user to required data operations; use a separate technical release path for schema, foundation Genesis and platform opening. The new database must be explicitly isolated from the old schema and production data. Foundation Genesis is CLI-only; technical installation provenance is not a human User and cannot authorize runtime operations. Secrets and raw challenge material never enter manifests, ordinary provenance or logs. - The target provisioning entry point is [bin/provision-target.php](../../bin/provision-target.php) with explicit `--database=target` and `--database=staging` selectors. The production selector reads `IDY_TARGET_DB_*`, requires the fixed target identity `idio2plat`, and preserves the production safeguard. The staging selector additionally requires `IDY_STAGING_DB_NAME` to match `IDY_TARGET_DB_NAME`, rejects `idio2plat` and production-looking names, and refuses a non-empty database. Neither selector runs from HTTP startup. Both apply migrations and foundation-only Genesis, install the approved Operation/Governance prerequisites, then apply the release-bound platform-opening mapping and record its evidence in `platform_opening_applications`. The mapping is `idy-platform-opening-effects` version `1`, release `IDY-PLATFORM-OPENING`, canonicalisation `json-object-keys-recursive-v1`, with pinned SHA-256 `3f47a5e29e5704b9d85696ec31259d6b7e3e4a4706f9cc3cd6ea7eaed171ef43`; it installs the `principal.register`, `principal.confirm` and `business.create` Operations (the first two are legacy identifiers for the User registration and confirmation Operations) plus the platform Policy. Provisioning validates that checked-in artifact rather than generating a new mapping. Opening is idempotent only for the exact same release, artifact, Genesis, mapping and effect inventory. `APPLIED`, `ALREADY_CURRENT`, `CONFLICT` and `RECONCILIATION_REQUIRED` are recorded in the opening ledger as applicable; `NEW` is only a transient marker for an incomplete pre-application record. Opening evidence is not represented as schema migration, Genesis run, normal Command execution or IDY-008 workflow execution. Conflicts and incomplete prior applications fail closed for reconciliation. Do not supply production credentials as command-line arguments, use test selectors, or treat a successful pre-opening stage as a production release. - First-milestone files are text/source references. Later binary upload storage is outside the web root, nonexecutable, addressed by opaque handles and served through authorised reads. External credential encryption is unnecessary before a live connector is introduced; retained crypto observations above are not new-runtime certification. - Back up the isolated demonstrator database daily and before schema changes; retain seven daily encrypted backups for this nonproduction milestone, with keys separately controlled. Rehearse restore into another isolated database and verify object/revision/Command links before release. These operational defaults are not a universal legal retention policy. - Keep addressable business history and retired objects without automatic purge in the demonstrator. Restrict access to historical evidence; any later retention/purge job must preserve applicable obligations and reference explainability rather than silently rewriting history. Avoid unnecessary sensitive data in fixtures. - Run the CLI dispatcher as the same release with bounded database claims and a distinct technical executor identity recorded as execution provenance only; it has no independent authority and operates under authority delegated by a User (see [delegated authority for automation](../architecture/identity-and-governance.md#delegated-authority-for-automation)). Report health, expired claims, failures and reconciliation-required work; a process restart never implies an Action failed or should be resent. Operators resolve unknown effects through authorised recorded recovery, not direct SQL state edits. ### Definition publication authority configuration The initial publisher is the already-established, active project-owner User. The minimum binding is the non-secret target configuration value `IDY_TARGET_DEFINITION_PUBLISHER_PRINCIPAL_ID` (legacy identifier for the User UUID), containing that User's exact UUIDv4. Parse it through the existing `TargetRuntimeConfig` environment configuration path. This identifies an existing User; it must never create one or be inferred from an Explorer allowlist, registration order, email address, generated identity or manifest. Missing, malformed, unresolved or inactive identity fails closed. The configured UUID is configuration, not a credential; do not treat it as proof of a human request or print it unnecessarily. The existing `TargetProvisioningRunner` owns normal platform installation, but its initial `run()` path requires an empty database and occurs before a human User exists. Therefore the grant and Policy are installed by a separate explicit post-owner configuration invocation owned by this same provisioning boundary, after the User has been established through ordinary registration/confirmation. The invocation must verify the selected target/staging database identity and that the platform foundation/opening is current before changing state; serialize through the existing runtime coordination boundary; and use the existing platform AuthorityGrant/Policy descriptors and generic Object repository. It installs only the configured User's direct platform grant for `definition.publish` on the universal Definition Type and the matching active platform Policy. Stable object identity and exact matching existing values make the step idempotent; partial, conflicting or mismatched state fails closed. This is a normal installation/configuration operation for an existing User, not a bootstrap protocol or self-authorising CLI. It creates no User or credential; it is not part of Genesis, the immutable platform-opening artifact, onboarding, HTTP startup or authority reassignment. The protected target configuration supplies the UUID, while the internal provisioning invocation performs the installation. Publisher reassignment/revocation and a general authority-management Operation remain deferred. No separate publication store, schema or migration is required by this binding. Do not run setup, bootstrap, password provisioning, restore or deployment as a documentation check. Runtime evidence must include the relevant [invariant tests](development.md#invariant-test-specification), not just successful login rendering.