← Back to directory

implementation-plan.md

implementation/implementation-plan.md · 107.5 KB · 2026-11-02 12:48

Idiosyncrasy — Implementation Plan

Version: 2.2 Source basis: Current Idiosyncrasy documentation at https://docs.idiosyncrasy.co.uk/docs/ Prepared: 2026-09-13 Status: Implementation planning document; not evidence that any mechanism below has been built or verified.

This is planning source material, not a canonical architecture owner, implementation contract or current status record. Use the following classification:

| Classification | Location / authority | |---|---| | CURRENT | Section 24.1 executable dependency order, bounded by the canonical owners and current task scope | | COMPLETED | Implementation status; this plan is not evidence | | NEXT | Only the explicitly requested bounded task; no stage is implied by this document alone | | DEFERRED | Sections marked Deferred/Later, the roadmap and current status limitations | | SUPERSEDED | Any earlier sequence or instruction that conflicts with section 24.1, a frozen implementation contract or current status | | HISTORICAL | The v2.0 backlog and historical planning inventories retained for traceability |

Do not read this document in full for an ordinary implementation task. Read the relevant current section only, then the canonical owner, applicable implementation contract, development guidance and status evidence. Sections 25 onward contain mixed acceptance, guardrail, traceability and historical material; they do not override the classification above.


1. Purpose

This document translates the current Idiosyncrasy documentation into a dependency-ordered engineering plan.

The current documentation is the source of truth for the product and architecture. This document must not redefine the settled semantic contracts D01–D10. Where the documentation already chooses an implementation mechanism, that mechanism is adopted. Where it deliberately leaves an implementation detail open, this document chooses the smallest conforming mechanism necessary to build the first runtime.

The initial implementation target is a generic Business-scoped demonstrator, operating on the generic Idiosyncrasy runtime. The goal is not to create or assume a Spearmint Design Business or build a conventional CRM first. The goal is to prove that a business can be represented, operated and extended through the universal runtime without bespoke business-code foundations.


2. Authoritative Source Hierarchy

The implementation must follow the documentation authority model:

1. Current canonical product and architecture documentation. 2. Settled D01–D10 decisions. 3. Current product roadmap and capability definitions. 4. Current implementation documentation. 5. This implementation plan. 6. Existing/legacy code only as implementation reality and reuse evidence, never as the new domain model.

The documentation explicitly distinguishes:

Implementation must preserve this distinction.

Contract notation

Each prescriptive addition in this plan uses these boundaries:

Primary documents

Archived sources are provenance only and are not current build authority.


3. Owner Decisions Applied to This Build

The project owner has explicitly selected the following implementation context:

| Decision | Choice | |---|---| | Initial hosting | Existing web server/hosting | | Backend | PHP 8.3.33 | | Framework | None | | Database | MariaDB 10.5.26 / InnoDB | | Database access | PDO + pdo_mysql | | Dependency management | No Composer; native autoloader owned by Idiosyncrasy | | Autoloading | Native first-party PSR-4-style autoloader | | Frontend | Server-rendered UI with small JavaScript enhancements; frontend framework remains deliberately TBD | | Authentication | Owned by Idiosyncrasy | | Business context | Independent Business identity and governed Business-scoped isolation from foundation | | First demonstrator | Spearmint Design | | Runtime shape | Modular monolith, distribution-ready by contract | | Infrastructure | Smallest production-capable foundation; no premature microservices | | AI | Optional; platform remains useful without an AI provider | | Implementation detail | Near-executable practical specification, without prescribing every line of code |

The current live implementation architecture aligns with PHP 8.3.33, PDO + pdo_mysql, MariaDB 10.5.26/InnoDB, an explicit composition root, a modular monolith, server-rendered presentation and small JavaScript enhancements. No application framework or Composer is used. PSR-4-style namespaces and autoloading may still be used, but autoloading is implemented by a small first-party bootstrap loader.


4. Non-Negotiable Architectural Constraints

4.0 Platform Governance Foundation Build Slice

The first build slice implements explicit platform/business scope within the universal model. It reuses AuthorityGrant, Policy, Operation, the trusted handler registry and one CommandHandler. Platform authority is direct User authority with no Membership and no Business; Business authority remains Membership-bound and scope-local. The trusted business.create handler generates Business and initial governance identities, and the platform Command branch persists its Command/evidence record with the nullable platform evidence scope. The bounded User admission Operations (registered as principal.register and principal.confirm, legacy identifiers for the User registration and confirmation Operations) use the same governed Command boundary; broader platform mutation coverage remains outside this slice.

4.1 Universal semantic model

All persistent and addressable platform data uses:

{
    id: <unique address>,
    type: <semantic type>,
    value: <typed/configured value>
}

This applies to business objects, types, relationships, configuration, knowledge, permissions, workflows, workflow nodes where independently addressable, events, views, policies, commands, executions and other addressable concepts.

No capability may introduce a competing foundational data model.

4.2 Physical database is not the semantic model

The universal model does not require a single SQL table, EAV storage, graph database or JSON-only database.

The approved initial physical mechanism is a dedicated MariaDB database with relational support structures and typed JSON values. The database implements the logical model; it does not redefine it.

4.3 One Business Graph

Business data, definitions, configuration, workflows, knowledge, events, permissions and other addressable concepts participate in one connected model.

A Customer reused by CRM, projects, marketing, forms and reporting remains the same addressed object.

Connectivity does not grant authority and graph traversal does not itself infer semantic truth.

4.4 Authority is explicit

Authentication, user identity, Business context, membership, AuthorityGrant, Policy, approval and technical execution identity remain distinct.

A business relationship must never silently become permission.

4.5 Deterministic runtime

Core operations must function without AI.

AI output is an input/proposal subject to the same validation, authorization and approval boundaries as human-authored changes.

4.6 Command-centred mutation

All consequential mutations use one authoritative Command pipeline.

HTTP, UI, workflow, CLI and AI adapters must not create alternative mutation paths.

Repositories are storage mechanisms, not public mutation endpoints.

4.7 Durable authority

Committed database state is authoritative.

Caches, read models, indexes and in-memory state cannot certify a mutation or override durable versions.

4.8 Explicit concurrency

Updates use expected versions.

Stale updates are rejected. There is no last-write-wins fallback.

4.9 Explicit Unknown/Reconciliation

A lost response after possible commit is not treated as failure.

Unknown external outcomes are not automatically repeated.

4.10 No arbitrary runtime code generation

Business behaviour is represented through types, configuration, policies and controlled workflows. Generated configuration is not arbitrary generated PHP.


5. Initial Runtime Architecture

5.1 Deployment shape

Use a single deployable PHP application initially.

Web Server
    |
    v
PHP Front Controller
    |
    v
HTTP Controllers
    |
    v
Application / Command Services
    |
    +---- Validation
    +---- Business Context
    +---- Authority / Policy
    +---- Workflow
    +---- Retrieval
    |
    v
Repositories / Persistence Adapters
    |
    v
MariaDB 10.5.26 / InnoDB

A later distributed deployment may separate responsibilities, but no semantic contract may depend on process boundaries.

5.2 PHP structure

Use:

Do not wire old direct-SQL controllers into the new runtime.

5.3 Suggested repository structure

/app
    /Runtime
        /Auth
        /Business
        /Commands
        /Objects
        /Types
        /Relationships
        /Policies
        /Events
        /Workflows
        /Knowledge
        /Retrieval
        /Views
        /Content
        /Integrations
        /Analytics
        /AI
        /Governance
        /Persistence
        /Http
        /Presentation
    /Legacy              # existing code, isolated and not authoritative
/bin
    bootstrap.php
    dispatch.php
    ...
/config
/database
    /migrations
    /seeds
/tests
    /Unit
    /Integration
    /Concurrency
    /Security
    /Acceptance
/public
    /assets
/docs

The exact directory grouping may be adjusted during implementation if it preserves the responsibility boundaries. The fourteen conceptual responsibilities do not require fourteen PHP modules/services.

5.4 Legacy Isolation and Target Cutover

Semantic Contract: legacy code cannot become an alternative authority for target-runtime business state.

Implementation Contract: the target runtime has a distinct front controller/public entry point, fresh dedicated database, session cookie name and runtime configuration namespace. Its routes use only App\Runtime services and the new database. Target routes never invoke legacy controllers, repositories, tables, setup scripts or mutation paths. The legacy application may remain reachable during development only through a segregated legacy deployment or hostname/path with its existing database and its own session cookie. There is no old-data migration.

Before target release, deploy only the target entry point and target routes at the production runtime location. Disable or remove legacy routing from that entry point; a reverse proxy/path rule may direct an explicitly retained legacy environment elsewhere, but it must not share target sessions or database credentials. Reusable legacy material is limited to reviewed visual tokens, narrow PHP/PDO configuration lessons and isolated helper patterns. It must be copied/refactored behind the target boundary, never called as a target mutation dependency.

Implementation Detail: the exact hostname, path prefix, deployment directory and session-cookie names may be chosen for the host, provided the two applications remain isolated.

Deferred/Later: migration, compatibility endpoints, mixed-record views and gradual record-by-record conversion are not in scope.


6. Physical Persistence and First-Slice Database Contract

Create a fresh dedicated database for the new runtime. Do not use the old marketing schema as the foundation and do not create a migration/compatibility layer unless separately requested.

Native autoloading policy

Composer is deliberately excluded. The application owns its bootstrap and class loading.

Use PHP namespaces with a PSR-4-compatible directory convention, but implement the loader in a small first-party file such as bootstrap/autoload.php.

The loader must:

Do not recreate Composer's package-management functionality. We only need class loading for the first-party application.

Native test bootstrap

Implementation Contract: PHPUnit 11 is used without Composer on PHP 8.3.33. PHPUnit 11 requires PHP 8.2 or newer, so the selected major version is compatible with the production CLI; the exact patch release must still be pinned and smoke-tested against PHP 8.3.33. The repository stores the pinned PHAR under tools/, with the exact version and SHA-256 recorded in a sibling checked-in metadata file. Test bootstrap requires the same first-party runtime autoloader. The executable test command is:

php tools/phpunit-11.phar --bootstrap tests/bootstrap.php tests

The acquisition/refresh procedure verifies the recorded SHA-256 before replacing the PHAR. The test command, PHP version and MariaDB fixture configuration are recorded as evidence when the suite first runs.

Implementation Detail: the exact PHPUnit 11 patch release and download procedure may be selected during the foundation task, then locked by version and hash.

Deferred/Later: Composer, Composer scripts and dependency-managed test packages are excluded.

MariaDB 10.5 compatibility boundary

Implementation Contract: all SQL and DDL must run against MariaDB 10.5.26 with InnoDB. The implementation may use enforced CHECK constraints, DATETIME(6), unsigned integer versions, InnoDB row locks, named advisory locks and INSERT ... ON DUPLICATE KEY UPDATE, subject to focused execution checks on the production-compatible server. JSON values use MariaDB-compatible JSON text semantics; do not rely on MySQL binary-JSON behavior, MySQL 8-only functions or MySQL-only DDL shortcuts. Generated columns/indexes may be used only for declared scalar filters after MariaDB verification.

Migration atomicity must be determined per MariaDB 10.5 statement rather than assumed from MySQL behavior. The forward-only migration ledger, checksum verification and tested repair path remain required for any non-transactional DDL.

6.1 Authoritative object rows

Semantic Contract: all persistent/addressable concepts remain universal objects. A relational support table never becomes a competing domain model.

Implementation Contract: use the following first-slice tables. All identifier columns are CHAR(36) CHARACTER SET ascii COLLATE ascii_bin; all recorded timestamps are DATETIME(6) in UTC; versions are BIGINT UNSIGNED; all tables are InnoDB with MariaDB-compatible utf8mb4 JSON/text values.

| Table | Required columns | Keys and constraints | Purpose | |---|---|---|---| | objects | id, type_id, type_revision, scope_kind, nullable business_id, version, lifecycle, value_json, created_recorded_at, updated_recorded_at | PK id; version >= 1; scope_kind is platform or business; check that platform rows have no Business and business rows have one; index (business_id, type_id, lifecycle, id) | Authoritative current typed state. lifecycle is only active or retired at this layer; business State remains a typed reference in value_json. | | object_revisions | object_id, version, type_id, type_revision, lifecycle, value_json, recorded_at, nullable command_id, nullable provenance_id | PK (object_id, version); FK object_id -> objects.id ON DELETE RESTRICT; index (type_id, type_revision) | Immutable retained representation of every committed object version, including version 1. | | event_index | event_id, business_id, event_type_id, nullable subject_id, nullable command_id, nullable causation_event_id, nullable correlation_id, occurred_at, recorded_at, auto-increment sequence | PK event_id; unique sequence; indexes (business_id, event_type_id, sequence) and (command_id) | Query support for canonical Event objects. Event payload and provenance remain in the Event object's typed value. | | transition_index | transition_id, subject_id, business_id, nullable before_state_id, after_state_id, subject_version, command_id, recorded_at | PK transition_id; indexes (subject_id, subject_version) and (business_id, recorded_at) | Query support for canonical state-transition occurrence objects. |

objects.type_id, objects.business_id, and typed references inside value_json deliberately have no database foreign keys to objects: the root self-describing Type and mutually-referencing genesis graph cannot be inserted under those foreign keys. The Type validator and controlled-manifest validator must resolve them before normal commit and before genesis commit respectively. Support tables use restrictive foreign keys where the referenced current object can already exist. No object row is hard-deleted in the first slice.

Implementation Detail: column order, generated names for check constraints, and JSON serialization implementation are not architectural choices. JSON is retained as typed object value; the only first-slice JSON fields eligible for indexed retrieval are declared scalar properties in the active Type revision, materialized as generated columns/indexes only when a declared list filter needs them.

Deferred/Later: type-family inheritance, arbitrary JSON-path indexes, partitioning, full-text/vector indexes, bitemporal storage and hard-redaction jobs are not initial mechanisms.

6.2 Governance, execution and derived support rows

Implementation Contract: these support structures protect the universal model; their rows are not a second semantic foundation.

| Table | Required columns and constraints | Purpose | |---|---|---| | credentials | principal_id PK/FK to objects.id (legacy identifier for the User), password_hash, password_changed_at, nullable disabled_at; hash is never selected by generic object retrieval/export | One password credential per registered User, subject to confirmation and lifecycle state. | | auth_rate_limit_buckets | PK (scope, subject_hash, window_started_at); attempt_count; fixed 15-minute UTC windows; increment atomically with one INSERT ... ON DUPLICATE KEY UPDATE | Durable five-failures-in-15-minutes control for separately hashed user and source-address subjects. | | command_keys | command_id PK/FK to Command object; principal_id, business_id, operation, fingerprint BINARY(32), admitted_at; command ID is globally unique | Binds a stable Command identity to exactly one canonical semantic request. A repeat ID must match every bound value and fingerprint or is a conflict. | | relationship_index | relationship_id PK/FK; business_id, relationship_type_id, source_id, target_id, active; indexes in both endpoint directions | Transactionally maintained derived traversal structure. Never an authority source. | | relationship_slots | PK (relationship_type_id, endpoint_role, endpoint_id, slot); relationship_id unique; a slot exists only while a max-one relationship is active | Enforces initial 0..1 cardinalities, including one active Project originating from one Qualification. | | workflow_trigger_keys | PK (event_id, workflow_id, workflow_revision); workflow_execution_id unique | Ensures one committed Event starts at most one execution of an applicable active workflow revision. | | workflow_dispatch | workflow_execution_id PK/FK; dispatch_state, eligible_at, nullable lease_token, nullable leased_by, nullable lease_expires_at, step_count, nullable last_error_code; eligibility index (dispatch_state, eligible_at, workflow_execution_id) | Durable dispatcher eligibility and lease state for canonical WorkflowExecution objects. | | runtime_coordination | exactly one seeded row id = 1 | Every normal consequential mutation locks this row with SELECT ... FOR UPDATE before final validation. It serializes the first runtime across PHP processes. | | schema_migrations | migration_id PK, checksum BINARY(32), applied_at, release_id | Migration ledger. The runner takes a named database advisory lock, verifies each applied checksum, applies one forward-only migration transactionally where the specific MariaDB 10.5 DDL permits, and records it only after success. |

For the first slice, the coordination-row lock gives a single ordering for normal mutation, governance change, cardinality reservation and required history writes. Reads do not acquire it. External calls never run under it. A transaction rolls back every local state, revision, index, event, transition, Command/Attempt and success record if any required write fails.

Implementation Detail: generated-column names, advisory-lock timeout, exact error-code strings and repository method names are local choices. A migration whose DDL cannot be transactionally reversed must be explicitly marked non-transactional and have a tested forward repair; it may not be silently retried.

Deferred/Later: sharded coordinators, row-level fine-grained lock optimization, generalized cardinality above 0..1, asynchronous indexers and online schema-change tooling.

6.3 Supporting typed objects

These remain addressable platform objects even where physical support structures exist:

A support table exists to make the runtime safe and efficient; it does not become a competing semantic universe.

6.4 IDs and time

6.5 Indexing

Initial indexes should support:

Use stable ID cursor pagination.

Default page size: 50. Maximum initial page size: 100.

Authority filtering occurs before disclosure.

No asynchronous search index is required initially.


7. Object and Type Runtime

7.1 Type definition

A Type is itself an addressable object.

A type definition must be capable of describing:

Unsupported inheritance/composition must be rejected rather than guessed in the first runtime.

7.2 Definition revision lifecycle

Semantic Contract: Types, Policies, Workflows, Views and Business DNA are addressable versioned configuration; a later definition must not rewrite prior use.

Implementation Contract: each configuration object has immutable retained revisions in object_revisions and one current object row. Initial configuration lifecycle is draft -> active -> retired. A Business-scoped configuration item has at most one active revision for its object identity; activation is a governed Command that retires no historical revision. A new active revision supersedes the former current revision only for future selection. Restoration creates a new revision whose value references the restored source revision; it never mutates historical rows.

Instances bind type_id and type_revision at creation. They continue to validate and render against that revision until an explicit, validated upgrade Command creates a new instance revision. Workflow executions pin their Workflow revision; Actions, Decisions and transitions record each relevant Type, Policy and Workflow revision. Retiring a definition prevents its selection for new work, but does not erase existing instances, history or pinned executions. A changed dependency is rechecked before a pending workflow continuation; it either remains applicable, suspends for review, or requires a new Decision. No implicit workflow migration occurs.

Implementation Detail: the exact revision-number allocation, API shape and editor layout may be chosen locally.

Deferred/Later: concurrent branching/merging, type inheritance, bulk instance upgrades and automated compatibility migration are refused.

7.3 Validation

Every object entering the runtime must pass deterministic validation.

The same validation boundary applies to:

Validation does not grant authority.

Authority does not make invalid data valid.

7.4 State identity

Keep these separate:

1. State definition 2. Current state reference on an object 3. State-transition occurrence

A label such as approved is not itself a State identity.

Historical transitions retain the State definition/revision context used at the time.

7.5 Object lifecycle

For the demonstrator, prefer retirement rather than hard deletion where historical references matter.

Historical references must remain explainable subject to authorization and retention rules.


8. Business Graph and Relationships

Relationships are first-class addressable objects when they require independent identity, metadata, lifecycle, provenance or history.

Scalar references that do not require independent identity may remain typed values.

Relationship Types must define:

Relationship mutation must validate:

A relationship never grants permission merely because it exists.

Relationship history and temporal meaning follow the Time/Event contract.


9. Identity, Authentication and Business Context

9.1 Authentication

Implement server-side PHP sessions using:

The target runtime begins with User registration and confirmation; the existing login-only slice is historical/reuse material and does not satisfy that admission lifecycle.

Implementation Contract: password credentials use Argon2id through PHP's password API, have a 14-character minimum and are rehashed on successful login when PHP reports that they are outdated. Login returns a generic failure response, performs a dummy verification for an unknown identity, and checks atomic identity-hash and source-address-hash rate-limit buckets. 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. A successful password authentication regenerates the session identifier. Target sessions use Secure, HttpOnly and SameSite=Strict cookies, a target-only cookie name, a 30-minute idle lifetime and an eight-hour absolute lifetime. Logout, credential disablement and password change invalidate the current session; a subsequent request must reload the credential and membership state rather than trust a cached session grant.

The first runtime supports password assurance only. A configured operation requiring stronger assurance is refused until its assurance mechanism exists. Registration and confirmation are implemented as separate narrowly bounded pre-authentication admission Operations; password recovery, SSO and MFA enrollment remain outside this initial contract unless separately approved.

9.2 Identity distinctions

Keep distinct:

Authentication identity
        |
        v
User (authenticated account)
        |
        v
Business membership
        |
        v
AuthorityGrant
        |
        v
Operation / target

A Person, Organisation or Business object is not automatically an authenticated User; a Person is a Business-scoped individual profile, and neither a User nor a Person requires the other.

9.3 Business-scoped isolation and entitlement

Independent Business identity and Business-scoped isolation exist from the beginning. This is an isolation and authority boundary, not a fixed ownership or tenant model.

Every Business-scoped read/write/retrieval/relationship/file/integration operation must resolve and enforce Business context.

Business-scoped operational execution must also satisfy the canonical subscription entitlement gate in subscriptions and entitlements (intended future architecture; all Businesses are currently treated as active and no entitlement is enforced). business.create is free and never entitlement-gated. This implementation plan does not define a second subscription mechanism.

Business selection is a context selection, not a grant.

9.4 Initial UI identity flow

Login
  ↓
Authenticated User
  ↓
Authorised Business list
  ↓
Business context
  ↓
Application UI

The first Idiosyncrasy bootstrap Business does not automatically grant access to Spearmint.

Implementation Contract: a credential authenticates one User. An active Membership grants selection of a Business context only; a separate active AuthorityGrant authorizes named operations against declared object Types, object IDs or configuration scopes. Every read, mutation, history lookup, relationship traversal, export, file access and workflow continuation resolves the User and current Business server-side. Platform-scoped definitions are not publicly readable by default and need an explicit platform/configuration grant. Cross-Business sharing is unsupported and denied.


10. Authority and Policy

Policies are versioned typed objects with:

The initial expression interpreter supports only an allowlisted deterministic language:

Never use eval or arbitrary generated code.

Unknown/missing input is not a successful condition.

A Policy relationship does not automatically establish precedence.

When conflict cannot be deterministically resolved, stop the effect and create a scoped human Decision request.

A Decision:

Exceptions/delegations are explicit typed arrangements with scope, period, conditions and provenance.

Implementation Contract: an Approval is a Decision object that binds the proposal/action identity, Business, target object IDs and revisions, Policy revisions, determination, approving User and optional expiry. The approver must hold current approval authority at Decision commit and again when the approved Action commits. Email links, notification reads and an asserted user ID are not approval. Delegation is represented and audited but no onward delegation is supported in the first slice. Revocation, retirement or changed dependencies invalidate future use after commit-time recheck, never past evidence. A worker records a distinct technical executor identity as execution provenance only; it has no independent authority, and business authority derives from the authority delegated by a User (see delegated authority for automation).

Deferred/Later: role-group management, delegated chains, MFA, recovery, SSO, service-account APIs and cross-Business sharing.


11. Command and Mutation Pipeline

This is the central runtime path.

HTTP / UI / Workflow / CLI / AI
            |
            v
       CommandHandler
            |
      Authentication
            |
      Business Context
            |
      Type Validation
            |
       Authority
            |
         Policy
            |
   Expected Version Checks
            |
     Transaction / Commit
            |
   Revision + History + Provenance
            |
        Command Result

11.1 Command identity

Every consequential operation receives a stable Command ID.

Canonicalize the semantic request by:

Hash the canonical representation with SHA-256.

Bind it to:

11.2 Admission

In a short transaction:

1. lock the coordination row; 2. validate admission authority; 3. create/verify unique Command identity; 4. create Command object; 5. create Action Execution; 6. create initial Attempt/provenance; 7. detect duplicate versus conflicting request fingerprint.

11.3 Commit

Reload authoritative state and governance dependencies.

Recheck:

Perform all required local mutations in one transaction.

Update with expected-version predicates:

WHERE id = :id
  AND version = :expected_version

A zero-row update is stale/incompatible.

Never silently fall back to last-write-wins.

11.4 HTTP contract

Mutation endpoint:

POST /commands

Command status:

GET /commands/{id}

Initial response semantics:

Do not expose inaccessible object existence through error differences.

11.5 First-milestone execution records

Semantic Contract: Command, Action Execution, Attempt, Outcome, Event, state-transition occurrence and Provenance remain distinct addressable concepts.

Implementation Contract: a Command is the semantic request; it has one Action Execution in the first local runtime. A Command and its Action Execution use lifecycle admitted -> executing -> settled or admitted/executing -> reconciliation_required. An Attempt records one try with started -> settled; every retry creates another Attempt. An Outcome is a separate addressable object linked to the settled Attempt and uses exactly one of succeeded, rejected, failed or unknown. unknown moves the parent Command and Action Execution to reconciliation_required; an authorised reconciliation Command records later evidence and a new Outcome without deleting the unknown Attempt.

The first Command envelope contains id, operation, business_id, targets, expected_versions, payload, source, and canonicalization version 1. The server supplies authenticated user, technical executor and correlation identifier; client payload cannot supply them. Canonicalization recursively sorts object keys, retains array order and scalar type, rejects duplicate keys, non-finite numbers and unsupported values, then encodes with one documented PHP JSON flag set before SHA-256 hashing. Existing changed targets require an expected version. Creates require a requested new object ID; an existing ID is a conflict. A multi-object Command lists expected versions for every pre-existing changed target. New IDs generated during first execution are stored in the Command result and reused when its stable Command ID is redelivered.

An Event is a canonical addressable occurrence, not a request or a notification. First-milestone Events are required for object creation, declared State transitions, Qualification Decisions, workflow start/resume and Command reconciliation. object.create emits exactly one object.created Event in the same atomic commit as the new object, revision, provenance and required Command evidence. The Event records the addressable object creation occurrence through the existing Event object, Event Type and event_index infrastructure; it does not introduce a second Event or audit architecture. Authorization for object.create targets the requested object's Type within the server-resolved Business/configuration scope, using the existing operation-plus-target-Type AuthorityGrant model with current server-resolved Membership, Business and Policy checks. The new object identity is not itself an authorization target before creation, and request/manifest claims or relationships cannot grant authority; its stable identity is retained in the resulting Command, provenance and evidence. Each Event has a stable Event Type object reference, Business, subject references, occurrence/recorded time, provenance, optional causation Event and correlation identifier; event_index supplies a durable sequence for deterministic scanning. A declared State change creates one addressable transition occurrence with before/after State-definition references and one corresponding object.transitioned Event in the same local transaction. object.update and object.relate retain the generic policy that an ordinary value update or relationship operation emits an Event only when the declared operation requires one.

The Command commit creates required revision, provenance, transition and Event records atomically with the business effect. A workflow consumer claims a committed Event by inserting workflow_trigger_keys in the same coordination-locked transaction; unique-key conflict means it was already admitted. Consumers record their own execution outcome and never treat Event delivery as proof of an external Effect. Current object rows remain authoritative: this is not event sourcing and Events are not used to reconstruct state by default.

Implementation Detail: enum storage, error-code wording, JSON flags and internal class names may vary only if the canonical bytes remain stable for canonicalization version 1 and tests prove duplicate handling.

Deferred/Later: event broker, cross-process subscription service, global causal ordering, arbitrary replay and exactly-once external delivery.


12. Events and History

Events, transition occurrences, Commands, Attempts and outcomes remain distinct concepts.

Required history must be committed coherently with the state change.

Historical records preserve:

A correction must not silently rewrite the historical meaning of a prior event.

Events are available to workflows without requiring capability-specific event models.

The event and transition records specified in section 11.5 are the required first implementation depth. They must be authorization-filtered on inspection and retain references even when related current objects are retired. They do not require a general activity feed, notification service or event-sourced projection system.


13. Workflow Runtime

13.1 Definitions

A Workflow Definition is an addressable, versioned configuration object.

Keep separate:

Implementation Contract: a Workflow Definition follows draft -> active -> retired; only one active revision of the selected workflow is eligible for a trigger. Draft definitions are inspectable only by authorized configuration users and never dispatch. Retirement prevents new trigger admission while retained executions remain pinned to their recorded revision.

13.2 Initial supported execution

The first interpreter supports:

Unsupported node types must be rejected rather than silently approximated.

Each node has a stable node address within its pinned definition revision, one declared input binding, explicit permitted output/continuation names and no implicit controller order. condition uses the allowlisted Policy expression language and treats unknown/missing input as non-success. wait_for_event records event type, correlated subject/execution reference and optional UTC wake time; a matching committed Event resumes only that execution. request_approval records the proposed subject/version, required action, applicable Policy/version and permitted reviewer scope, then waits for a Decision Event. local_command identifies one exact approved Operation Contract identity and revision and maps only declared workflow inputs to that Command envelope. The Operation Contract is interpreted by its fixed trusted handler; the node does not supply executable behavior or a caller-defined effect list.

13.3 Execution persistence

A WorkflowExecution records:

13.4 Dispatcher

Initial mechanism:

One dispatcher pass is limited to 100 steps.

Cycles or exhausted bounds result in a suspended/review-required state.

Implementation Contract: WorkflowExecution uses eligible, running, waiting, succeeded, failed, cancelled, suspended or reconciliation_required. A dispatcher claims only eligible executions by assigning a fresh lease token and 60-second expiry. Every update from a worker includes that token; an expired/changed token fences the previous worker. The intended dispatcher command is php bin/runtime-dispatch.php --once; production cron will invoke that command at least once per minute using the same release and a distinct technical worker identifier once the dispatcher is implemented. The current repository does not yet contain that command. The process makes no external call in the first workflow.

An unexpected process failure leaves the execution eligible after lease expiry only after the dispatcher reconciles the durable Command/Attempt record. It may create a new Attempt only for a local Command that has no settled Outcome; duplicate Command handling then prevents another semantic effect. Validation, denial and terminal failure are not automatically retried. An authorized cancellation Command may cancel an eligible or waiting execution before its next local Action; cancellation after an Action has started requires reconciliation and cannot erase prior effects. Every pass has a 100-step bound; a loop, exhausted bound, changed required dependency or unsupported continuation becomes suspended with an inspectable reason.

Deferred/Later: parallel branches/joins, recurrence, arbitrary timers, priority queues, workflow migration/re-entry/compensation, live integrations and automatic retry of unknown remote effects.

13.5 Scheduling

Initially support:

For local-time scheduling:

Do not implement a general recurrence language initially.


14. Retrieval

Structured retrieval is a platform capability, not an AI-only feature.

Initial retrieval must support constraints involving:

Apply authorization before disclosure.

Use direct authoritative MariaDB-compatible queries initially.

No vector database is required.

Optional semantic retrieval may later narrow candidates but cannot bypass structural authorization or replace deterministic retrieval.

Pagination:

14.1 First-milestone retrieval contract

Semantic Contract: Retrieval is authorized structured context assembly, not an AI-only search service.

Implementation Contract: before the first UI, implement only the governed Business identity projection used by Business selection, getObject(id) and listObjects(business, type, cursor, pageSize) plus declared Relationship traversal from an already authorized object. The Business identity projection resolves authorized active Memberships and returns permitted Business identity fields; it is distinct from ordinary Business-scoped object retrieval because the Business root is platform-scoped with business_id = null. getObject returns an authorized current object projection or the same non-disclosing absence result for inaccessible/nonexistent objects. listObjects requires an active Business context and Type ID, filters to active Business-scoped rows, applies field/relationship visibility before projection, orders by opaque object ID ascending and accepts an exclusive last-ID cursor. Page size defaults to 50 and is capped at 100.

No arbitrary JSON-path query, free-text search or client-selected SQL sort is supported. A Type/View declaration may opt a named scalar property into a list projection only after that property is validated and its generated-column index is added by a migration. Relationship selectors call the same authorized list/traversal operations; they never load a global label list. The first history view resolves a known object/revision by ID under the same authority checks rather than supporting general historical search.

Implementation Detail: SQL layout, repository method names and projection DTOs may vary.

Deferred/Later: type-family query, cross-type filtering, arbitrary property/range/time/provenance/ownership search, full-text/vector search, aggregates and saved queries.


15. Knowledge

Knowledge is first-class addressable data in the same model.

A document is a source, not automatically truth.

Knowledge must retain:

Initial implementation should deliberately avoid automated document extraction as a prerequisite.

Start with:

AI question answering is optional.


16. Views, UI and Presentation

16.1 Core principle

The UI is a projection of the model, not a separate business model.

Identity
   ↓
Business Context
   ↓
Authorised Object/Type Model
   ↓
View Definition
   ↓
Server-rendered UI
   ↓
Small JS enhancement

The first implementation intentionally avoids locking the project into React/Vue/etc.

The live specification explicitly calls for server-rendered view definitions with an allowlisted field/renderer registry and small JavaScript enhancements.

16.2 Initial screens

The first usable runtime should include:

1. Login 2. Logout 3. Business selection 4. Business dashboard/application shell 5. Typed object list 6. Object detail 7. Declared operation form 8. Revision/history inspection 9. Transition/provenance inspection 10. Command status

16.3 UI safety

All mutations go through Commands.

Hidden/disabled controls are not security boundaries.

Browser requirements:

AJAX is preferred for non-navigation actions, with safe conventional form fallback where practical.

16.4 First-milestone generic view/form contract

Semantic Contract: UI is an authorized projection of the same model and submits Commands; it has no business-state store.

Implementation Contract: implement only a server-rendered shell, login/logout, Business selector, Type-scoped object list, object detail, declared operation form, Command status and known-object revision/transition/provenance inspection. A View definition declares its Type ID, permitted list/detail fields, declared relationship sections and declared operation IDs. A Form definition declares one registered operation, the Type/State context, input field names and their renderer types. The initial renderer allowlist is text, textarea, number, date_time_utc, select, object_reference and read_only; unsupported renderers or fields cause a configuration error rather than fallback HTML.

The renderer obtains fields and permitted actions from authorized Type/View/Form definitions. It displays only committed values, includes expected versions and a stable generated Command ID in mutation forms, and maps submitted input only to the declared Command payload. Client-provided field names, Business IDs, operation IDs, object references and versions outside that declaration are rejected. Field/relationship denial and inaccessible objects use the same non-disclosing result as the retrieval service. The UI distinguishes validation denial, authorization denial, stale version, failed attempt, pending command and reconciliation-required status; it preserves entered input after safe rejection and never retries an unknown effect.

For an existing-object target, an Operation declaration may add presentation metadata: a human label, selection: existing, and one target_type_id. GET may use that binding to discover candidates through the authorized object reader and the authorized View projection for the resolved User and Business. The resulting option value is only the declared target role's object UUID; the browser cannot choose the Business, Type, handler or Operation revision. A target declaration without this metadata remains a deferred target-entry contract. POST maps selector values into the existing target envelope, and OperationInvocationService remains the sole final target/effective-Type authorization authority.

Implementation Detail: templates, CSS, AJAX implementation and presentation DTOs may follow the existing visual baseline while retaining server-rendered form fallback and keyboard/accessible-label requirements.

Deferred/Later: visual view builder, arbitrary renderer plug-ins, portal views, dashboards, autocomplete/global search and rich-content editing.


17. Bootstrap / Genesis

Semantic Contract: foundation-only genesis establishes the minimum generic storage, Type-of-Type and foundational vocabulary required to open the platform; it does not establish human identity, Business or authority state.

Implementation Contract: genesis runs only through a target CLI command against an empty database whose migration ledger matches the target release. It loads one immutable, versioned manifest with a digest and stable UUIDv4 seed addresses. The only permitted bootstrap exception is that the root Type definition may reference itself as type_id before ordinary Type validation exists. All other seed objects use the root Type or another seed Type declared in the same manifest. Object self-references have no database FKs; the genesis validator resolves every reference from the complete manifest before commit.

Inside one coordination-locked transaction Genesis inserts only current object rows and matching revisions for the root Type, foundational Types and required foundation occurrence/ledger vocabulary, validates references and writes technical installation provenance. It creates no human User, credential, Business, Membership, Business AuthorityGrant, Business Policy, owner, superuser, permanent administrator, customer View or human runtime actor. Failure rolls back all foundation rows and leaves no usable partial store. Re-run succeeds only when the manifest digest and every stable identity match exactly; a mismatched, populated or foreign store is refused.

After foundation Genesis, a separate deterministic platform opening/release installs the approved identity-lifecycle and platform business.create configuration using technical release provenance only. Normal runtime then follows registration -> confirmation -> authentication -> bounded onboarding -> business.create; every customer creation or configuration change uses Command -> validation -> authority/policy -> commit. Spearmint is created later through ordinary business.create, not through an implicit cross-Business bootstrap grant.

17.1 Normal Business creation after Genesis

Existing architectural rule: Genesis establishes only the initial Idiosyncrasy foundation. It is not a continuing privilege bypass. After Genesis, normal Business creation and configuration use the governed runtime.

Newly resolved governance decision: Normal Business creation is the platform-scoped business.create capability. It is not external provisioning, a generic object.create alias or Business-scoped administration because the target Business does not yet exist. An authenticated User must be authorized by the platform-level authority for this capability before an active Business context can exist.

The business.create operation creates, in one governed atomic bootstrap transaction:

The Membership kind is descriptive and does not create permanent ownership, an immutable administrator, a fixed hierarchy or an unrestricted superuser. AuthorityGrant and Policy remain independent governed objects. Relationships do not grant authority, and missing or conflicting Policy resolution fails closed. Genesis-only bootstrap_operator and platform.inspect_foundation values are not reused for normal Business creation.

Implementation/configuration dependencies: the approved platform-level authority source; the exact Operation Contract revision and trusted handler registration for business.create; the concrete initial AuthorityGrant operation/target-Type inventory; the concrete initial Policy configuration and rule inventory; and any Business-creation Event name not already fixed by the Event contract. User registration and confirmation have separate implemented Operation identities at revision 1 with trusted handlers platform.principal-register and platform.principal-confirm (legacy identifiers for User registration and confirmation); those admission dependencies are resolved and are not future work. The remaining Business-creation dependencies must be resolved without weakening the identity, isolation, authority or evidence rules above. The server resolves the initiating User and generates the Business identity; client authority claims are rejected.

The Command must retain the exact Operation identity/revision and use the existing Command identity, fingerprint and duplicate-delivery semantics. Business, Membership, AuthorityGrant, Policy, provenance and required history/evidence commit coherently or the operation leaves no usable partially governed Business. Required evidence identifies the initiating User, Business and governance revisions together with Command, Action Execution, Attempt, Outcome, Provenance and the applicable Business-creation Event/causal links.

Implementation Detail: protected-prompt library, manifest file format and root-Type field names are local choices, provided the manifest remains deterministic and auditable.

Deferred/Later: seed-manifest merging, import bootstrap, interactive superuser installation and an ongoing universal administrator flag.


18. Spearmint Design Demonstrator

Spearmint is the first demonstrator, not a bespoke application.

18.1 Business configuration

Represent Spearmint as a Business with:

No Spearmint-specific database foundation.

No Spearmint-only engine.

Implementation Contract: after runtime User admission and governed business.create, install a trusted, versioned, reusable Business-configuration release through the generic configuration Commands. The first product-owned configuration may define the bounded vocabulary and process for the resulting Spearmint Design Business, including Person, Organisation, Enquiry, Qualification, Project, Decision, WorkflowDefinition, WorkflowExecution, Event, StateTransition, Policy, ViewDefinition and required Business-owned relationship types. It must not contain a fixed Business or User identity, create the installing User, create Membership/AuthorityGrant prerequisites, or provision operational records. Reviewer Users, if later needed, must already exist under separate governed runtime operations and be referenced rather than provisioned by IDY-008; workflows have no identity of their own and operate under authority delegated by a User (see delegated authority for automation).

18.2 First bounded process

The approved first executable slice is:

Enquiry
   ↓
Qualification
   ↓
Project / Scoping

The larger lifecycle remains:

Enquiry
→ Qualification
→ Project/Scoping
→ Proposal
→ Internal Delivery Authorisation
→ Design
→ Design Acceptance
→ Development
→ Review
→ Final Acceptance
→ Launch
→ Handover
→ Completion

The three approval concepts must remain distinct; do not collapse them into a generic approved field.

18.3 Enquiry

Minimum configuration:

Creation occurs through Command.

No public intake connector is required initially.

Implementation Contract: Enquiry requires source, summary, received_at (UTC) and exactly one of an authorized Person/Organisation contact reference or contact_unmatched = true. Its declared States are received, qualification_submitted, rejected and scoped. An operator with create_enquiry creates it in received; the resulting local commit records provenance and one enquiry.created Event. The Event starts at most one execution of the active Spearmint workflow revision through the workflow_trigger_keys uniqueness constraint.

18.4 Qualification

An operator records:

An authorised reviewer records a scoped Decision.

Progression is blocked when:

Rejection remains historical.

Implementation Contract: Qualification requires its Enquiry reference, requirements, fit assessment, submitter User and submitted time. Its States are submitted, approved and rejected. Submission is a declared operator Command that creates the Qualification, relates it to the Enquiry, transitions the Enquiry to qualification_submitted and records qualification.submitted. The workflow waits for that Event, creates an approval request and waits for an authorized Decision.

The Qualification Policy permits a reviewer to create an approved or rejected Decision only when the exact Qualification and Enquiry revisions, applicable Policy revision and requirements are current, and the reviewer User differs from the recorded submitter. The Decision records its target versions, reviewer, determination, rationale and Policy revision; its commit transitions Qualification to approved or rejected and records qualification.decided. A rejected Decision transitions the Enquiry to rejected and ends the workflow. Missing evidence, conflict, stale inputs or absent authority leaves no progression effect.

18.5 Project / Scoping

A governed Action creates Project and source/customer relationships only after the applicable positive qualification Decision.

Required inputs:

Record coherently:

Duplicate delivery must not create another Project.

Implementation Contract: Project requires scope_summary, exactly one assigned responsible User and State scoping. The positive-decision continuation issues a local create_project_from_qualification Command. In one transaction it rechecks the exact positive Decision, all referenced revisions, reviewer authority, active Policy and Qualification state; creates the Project; relates Project to the Qualification and originating Enquiry; relates its responsible User; transitions Enquiry to scoped; records required provenance, Event and transitions; and reserves the Qualification -> Project active relationship slot. The slot allows at most one active Project for each Qualification. A later distinct Command that reaches the same Qualification gets a cardinality conflict; it must not create another active Project.

Initial relationship cardinalities are: Enquiry-to-Qualification 0..1 active, Qualification-to-Project 0..1 active, Project-to-originating-Enquiry exactly 1, Project-to-Qualification exactly 1, and Project-to-responsible-User exactly 1. Enquiry-to-Person and Enquiry-to-Organisation are each 0..1, subject to the explicit unmatched-contact representation.

The pinned workflow is on enquiry.created -> wait_for qualification.submitted -> request approval -> wait_for qualification.decided -> condition Decision.approved -> local create_project_from_qualification -> end; its false/rejected continuation ends with recorded rejection. It uses no external integration, AI action or automatic retry of a settled failure.

Deferred/Later: public form intake, customer matching, proposals, delivery authorization, design/review/launch stages, communication and live external effects.


19. First Executable Milestone

The first true milestone is not “a nice dashboard”.

It is:

> A user can authenticate into Idiosyncrasy, enter an authorised Business context, inspect addressable objects, and perform a governed state-changing operation through Command → Validation → Authority/Policy → Commit, with resulting state change and provenance/history addressable.

Acceptance requires inspectable:

And proves:


20. Development and Testing Strategy

20.1 Test stack

Semantic Contract: verification must prove the architecture's isolation, durability and recovery invariants rather than merely PHP syntax.

Implementation Contract: the foundation stage installs the pinned verified PHPUnit 11 PHAR and tests/bootstrap.php described in section 6. The suite reads an explicitly configured, isolated MariaDB database name that must match an IDY_TEST_ prefix; it refuses any other database. Each test case creates unique fixture IDs and rolls them back or truncates only that isolated database. Concurrency tests open two independent PDO connections. Fault injection is exposed only through test-only persistence/adapter seams, never HTTP parameters or production privilege bypasses.

The runner executes migrations from an empty test database before the integration suite, verifies schema_migrations checksums, and reports the PHP version, MariaDB version and exact PHAR hash. The required commands are:

php bin/runtime-migrate.php --database=test
php tools/phpunit-11.phar --bootstrap tests/bootstrap.php tests

The current implementation specification selects:

Do not use SQLite as evidence of InnoDB transaction/concurrency correctness.

Implementation Detail: test helper classes, fixture factories and test directory grouping are local choices.

Deferred/Later: browser-driver selection and a production-like load suite are not prerequisites for the first runtime. Manual keyboard/mobile checks remain release evidence until a browser suite is deliberately introduced.

20.2 Required test categories

Unit

Persistence/integration

Concurrency

Security

Workflow

Acceptance


21. Architecture Conformance Gates

The following gates are mandatory evidence, not documentation claims:

1. Universal representation — representative objects across business data, types, relationships, configuration, knowledge, workflows/nodes, events, views, permissions and integrations use the same primitive. 2. Type/relationship integrity — invalid values, missing endpoints and unauthorized changes fail. 3. Cross-capability reuse — the same object participates in multiple capabilities without parallel domain stores. 4. Human operation/no AI — core operations work with no provider and with provider failure. 5. Structured retrieval — deterministic type/relationship/state/time/permission constraints work before optional semantic retrieval. 6. Knowledge — sources, authority and provenance survive retrieval and change. 7. Isolation — cross-Business reads/writes/relationships/files/search/integration operations fail safely. 8. History/explanation — actions can be traced to actor, definitions, evidence and outcome. 9. Execution — stale changes, duplicates, retries, waits and cancellation obey the execution contract. 10. Generated presentation — views/forms render from definitions and remain authorized. 11. Controlled AI — AI output is schema-valid, authorized and approved where required. 12. Evolution — observation, suggestion, review, implementation and measurement remain distinct.


22. Security and Operations

22.1 Secrets

Keep credentials, encryption keys, provider tokens and deployment credentials outside source control and public web bundles.

The existing documentation identifies PHP external configuration as an established hosting-compatible pattern. The new runtime must not expose secrets through markup, logs, exceptions or AI prompts.

22.2 Files

Files use opaque handles and live outside the public web root where authorization is required.

Initial upload controls must include:

22.3 Deployment

Current release-foundation status

The current release boundary is reviewed in release/target-release.json and resolves to 131 source files. The deterministic manifest, target check, provenance-bound package builder and operator release command are implemented and locally checked. The guarded target-local launcher is limited to loopback database configuration and an isolated local session directory; production release source is an exact GitHub commit, not the arbitrary local working tree.

The historical release-staging/ snapshot has been retired and is no longer part of release verification. The operator command reports seven phases: local preflight, package creation/verification, production connection, staging/upload, remote verification, blocked activation and final result. It implements local packaging and remote staging/verification only. It transfers the exact locally verified package contents with one recursive SCP operation, then verifies the remote manifest, two control files, file list, byte counts and hashes. Remote verification invokes sh, -s and -- as separate SSH arguments while the read-only verification script is supplied through stdin; this preserves the Windows PowerShell/OpenSSH argument boundary and avoids corrupting the shell's set command. Native SSH/SCP failures retain executable, non-secret context, exit code, output and PowerShell exception diagnostics without printing arguments or password material. Progress output does not alter deployment semantics. It supports configured SSH keys and an operator-supplied native interactive SSH password fallback without persisting password material; strict host-key verification remains mandatory. Activation remains pending because no safe atomic switch or rollback mechanism is established for the documented Plesk/SSH layout. Normal releases remain code/assets only; provisioning, migration, Genesis, platform opening, database mutation and Plesk changes are not performed.

Verify before release:

On Plesk/Apache, verify directory-index precedence and relevant PHP/Authorization-header behaviour rather than assuming the host configuration.

Implementation Contract: a release contains one target public directory pointing to the target front controller, one non-public configuration location, one target database credential and the same application release for CLI dispatch. The migration command is php bin/runtime-migrate.php; it obtains the migration lock and refuses a checksum mismatch. A deployment applies migrations before enabling the release, runs the PHAR test suite against its isolated fixture database, verifies a target health command that checks configuration, PDO with pdo_mysql and migration state without exposing secrets, then enables the target entry point.

The dispatcher runs php bin/runtime-dispatch.php --once from cron at least once per minute as a distinct technical executor recorded as execution provenance only (no independent authority; it operates under authority delegated by a User) when that worker is implemented; the current repository does not yet contain bin/runtime-dispatch.php. Rollback is release-code rollback only when the applied migrations remain forward-compatible; otherwise release remains disabled and a documented forward repair migration is required. Production target deployment never shares credentials, sessions, routes or database with the optional legacy deployment.

The implemented staging path is explicit: php bin/provision-target.php --database=staging requires IDY_STAGING_DB_NAME to match IDY_TARGET_DB_NAME and rejects the fixed production identity idio2plat and production-looking names. The staging operator bundle is internal-only and is not published or consumed by the GitHub deployment workflow. The real Plesk staging filesystem, PHP-FPM environment and staging database remain deployment prerequisites rather than repository evidence.

22.4 Recovery

Backups must account for encryption key custody.

Record:


23. How Luna Must Use This Plan

This document is intended to begin the build, not merely describe it.

The build is deliberately staged. Luna must never be instructed to implement the whole document in one pass.

23.1 Stage discipline

For every stage:

1. Read the relevant current Idiosyncrasy documentation. 2. Read only the applicable section of this plan, especially the stage objectives, dependencies and exit criteria. 3. Inspect the repository before changing anything. 4. State the exact files/modules that will be changed. 5. Implement only the bounded stage/task. 6. Add or update focused tests. 7. Run the relevant test suite and static/lint checks available in the repository. 8. Inspect the resulting diff for architectural drift. 9. Report:

10. Stop at the stage boundary unless the next task is explicitly requested.

A stage is not complete because code exists. It is complete only when its exit criteria and tests are satisfied.

23.2 No silent architecture decisions

Luna may choose ordinary implementation details inside an already specified boundary. Luna must stop and report if it encounters a decision that changes:

Do not solve these by adding an ad-hoc abstraction merely to keep coding.

23.3 Stage gates

The following are hard gates:

Gate A — Runtime foundation: native autoloading, target configuration/PDO, migration ledger and no-Composer test bootstrap work only against isolated target/test databases.

Gate B — Controlled genesis: the root Type and minimum generic foundation vocabulary can be seeded atomically, repeatedly and without persistent human identity, Business or authority state.

Gate C — Normal access: authentication, current membership/grant/Policy checks and constrained authorized inspection are proven before normal Business data is exposed.

Gate D — Governed mutation: every consequential normal mutation writes Command, Attempt, Outcome, revision, provenance and required Event/transition records coherently before relationships, UI actions or workflows depend on it.

Gate E — Graph and UI: relationship authorization/cardinality and model-projection forms are proven before Spearmint configuration is operated by a user.

Gate F — Workflow: one committed Event starts at most one persisted execution; lease/restart, approval, waiting, cancellation and local-action recovery are proven before the first business process is accepted.

Gate G — Demonstrator: Spearmint Enquiry -> Qualification -> Project/Scoping passes happy and hostile fixtures without bespoke schema/code.

23.4 What Luna should build first

The first request is IDY-001 only.

Do not start by creating the CRM, dashboard, workflow engine or Spearmint screens.

The first objective is to establish a trustworthy runtime foundation. Once that is proven, proceed one bounded task at a time.


24. Corrected Implementation Stages

24.1 Executable dependency order

This is the only executable implementation order. It supersedes the v2.0 phase/backlog inventory retained later for traceability.

Bootstrap foundation
    ↓
Foundational definitions and controlled genesis
    ↓
Normal identity, Business context and constrained authorised inspection
    ↓
Governed Command mutation with history and provenance
    ↓
Relationships and model-projection UI
    ↓
Bounded workflow and dispatcher
    ↓
Spearmint configuration and demonstrator acceptance

| Stage | Bounded implementation contract | Exit evidence | |---|---|---| | IDY-001 Repository isolation audit | Classify legacy routes/schema as legacy only; select target public entry point, database/config namespace and session cookie. | A reviewed target/legacy route and database isolation matrix. | | IDY-002 Runtime foundation | First-party autoloader, composition root, PDO/configuration, target request boundary, migration runner/ledger, verified PHPUnit PHAR and safe test bootstrap. | Target boots; migrations and PHAR tests run only against an IDY_TEST_ database; no Composer dependency or instruction. | | IDY-003 Generic store and genesis | Universal object/revision tables and first-slice support tables; Type validator root; controlled genesis manifest/CLI. | Matching genesis is idempotent; mismatched/partial stores fail; credentials remain outside generic retrieval. | | IDY-004 Normal access and inspection | Password session, rate limit and CSRF controls; membership/grant/Policy evaluation; known-object and Type-scoped authorized inspection. | Login reaches only authorized Businesses; cross-Business/non-disclosure probes pass. | | IDY-005 Governed mutation/history | Command/Action Execution/Attempt/Outcome, expected versions, provenance, Event/transition records, shared command endpoint and reconciliation. | One declared local operation proves denied, stale, duplicate, failure, unknown and coherent-history behavior. | | IDY-006 Graph and generic UI | Relationship Types/objects/index/slots, authorized traversal, View/Form definitions and server-rendered generic projection. | A human completes declared work without direct SQL; UI cannot bypass Commands or disclose denied fields. | | IDY-007 Bounded workflow | Event trigger admission, sequential interpreter, wait/approval/local-command nodes, durable dispatcher and lease/recovery behavior. | One Event admits one execution; lease/restart/cancellation tests preserve Command and Attempt identity. | | IDY-008 Business configuration | Install an approved reusable versioned configuration release against an existing Business through target configuration Commands only. Spearmint is the first runtime Business use case, created separately through business.create. | No Spearmint table, controller or engine exists; reusable Type/Policy/Workflow/View declarations validate without provisioning identity, authority or operational data. | | IDY-009 Demonstrator acceptance | Run Enquiry -> Qualification -> Project/Scoping with happy, denied, stale, rejected, duplicate and no-AI fixtures. | First-milestone automated and required manual evidence passes. | | IDY-010 Surface UI | Provide a thin, usable Business-facing projection over the established foundation and a feedback loop for product learning. Reuse or adapt existing UI material where it conforms; all mutations use the governed Command path. | Bounded demonstrator/read-result surface implemented and HTTP-verified: the existing authenticated server-rendered shell, server-governed Business context, persisted Presentation Object graph, generic RenderablePresentation.elements projection and AuthorizedObjectReader provide the Enquiry -> Qualification read/result loop; configured Operations project declared inputs and existing authorized targets into a generic HTML form with readable labels, while continuing through OperationInvocationService and CommandHandler with AuthorityGrant/Policy and expected-version protection. IDY-010 implementation is closed at this bounded scope. The canonical dedicated idy010 artifact records 69/69 HTTP acceptance — PASS on 2026-09-19 with zero failures, zero runtime diagnostics and clean shutdown. The earlier 42/42 run is historical/superseded and 67/67 is an intermediate BUILD report. The Surface is intentionally not a finished/full product UI; the full configured PHPUnit result remains UNKNOWN — the full configured PHPUnit run was previously stopped before producing a final summary., and broader capabilities remain future/refinement work rather than unresolved IDY-010 implementation defects. |

An implementation task changes only one stage or a named exit-evidence gap. It identifies canonical owner, allowed files, required contract, focused tests, exact checks and remaining limits; it stops at the stage boundary. A task that discovers a contradiction in a settled semantic contract stops for owner review. Routine local choices remain implementation details.

24.5 IDY-010 and Provisional Future Scope

IDY-010 follows the dependency chain Foundation-only Genesis -> Platform Opening -> User Registration -> Confirmation -> Authentication -> Bounded Onboarding -> business.create -> IDY-008 -> IDY-009. It introduces no replacement identity, Business, Genesis, Command, workflow or IDY-009 contract. Its purpose is to make the existing foundation usable enough to learn from real Business interaction.

IDY-011 onward are provisional future stages whose scope, ordering, boundaries and detailed architecture remain subject to exploration. Do not derive implementation contracts, acceptance criteria, Operation identifiers, schemas, migrations, test requirements or module boundaries for those stages from this plan. Future stages may be split, combined, renamed or reordered as IDY-010 use produces evidence.

The provisional capability domains are recorded in the capability catalogue. They are not a stage list or a fixed module catalogue. The final balance between generic/model-driven and purpose-built UI, the configuration of Business DNA, and the use of optional AI-assisted interaction remain open questions for later PLAN/BUILD cycles.

24.2 First executable milestone acceptance

The milestone is satisfied only when an authorized human can authenticate, select an authorized Business, list and inspect permitted addressable objects, and complete one declared mutation through the shared Command pipeline. The resulting object revision, Command, Action Execution, Attempt, Outcome, provenance, Event and any State-transition occurrence are inspectable subject to authority.

Required automated fixtures prove: denied and cross-Business access disclose no protected data; stale versions change nothing; duplicate Command delivery makes one semantic effect; a failed required-history write rolls back the effect; a repeated Enquiry Event starts one workflow execution per active workflow revision; an expired dispatcher lease does not duplicate a local action; a rejected Qualification never creates a Project; and distinct Commands cannot create two active Projects for one approved Qualification. Required release evidence proves the no-AI path, migration/health checks, keyboard operation and mobile layout of the first UI.

Deferred/Later: the broader eleven MVP criteria remain product acceptance beyond this first executable milestone unless a later stage explicitly enables them.

24.3 Historical v2.0 planning inventory

The remaining phase, backlog, completion and summary material was retained to preserve prior planning identifiers and scope history. It is non-normative and must not be used to derive dependencies, toolchain choices or implementation work. Any old IDY-011 or later labels in this retained inventory are historical identifiers only, not current future stages or commitments. Section 24.1 controls all build order and stage acceptance; the provisional IDY-010+ boundary above controls current future planning.

Phase 0 — Repository and Runtime Foundation

Objectives

Exit criteria


Phase 1 — Authentication and Business Context

Build:

Exit criteria

A user can log in and select only a Business to which they have membership/authority.


Phase 2 — Object Persistence and Type System

Build:

Exit criteria

A valid typed object can be created, read and revised through the authoritative pipeline.


Phase 3 — Command Pipeline

Build:

Exit criteria

All consequential changes have one mutation path.


Phase 4 — State and History

Build:

Exit criteria

A state transition is independently inspectable and historically meaningful.


Phase 5 — Relationships and Business Graph

Build:

Exit criteria

A shared Person/Organisation/Business object can participate in typed relationships without duplicate capability-owned records.


Phase 6 — Policy and Authority Evaluation

Build:

Exit criteria

A valid object operation can still be refused because the actor lacks applicable authority or Policy permission, and a relationship cannot create authority.


Phase 7 — Model-Driven UI Foundation

Build:

Exit criteria

An authorized human can operate the first runtime without direct database access.


Phase 8 — Foundation Genesis and Platform Opening

Build:

The opening sequence then continues with User registration, confirmation/onboarding and authentication/authorization integration before ordinary business.create. No phase creates a Genesis User or Genesis Business.

Exit criteria

A fresh isolated database can be initialized safely and deterministically.


Phase 9 — Workflow Runtime

Build:

Exit criteria

A deterministic workflow can run without AI and survive restart/recovery.


Phase 10 — Spearmint Configuration

Build Spearmint configuration using the runtime only:

Exit criteria

No Spearmint-specific database table or engine is required.


Phase 11 — Spearmint Demonstrator

Implement:

Enquiry
→ Qualification
→ Project/Scoping

Prove:

Exit criteria

First executable milestone passes.


Phase 12 — Knowledge and Structured Retrieval

Build:

Exit criteria

A human can retrieve applicable knowledge without AI, with source and authority intact.


Phase 13 — Content and Communication Foundations

Build only the smallest reusable capability required by a demonstrator.

Potentially:

No broad connector catalogue.


Phase 14 — External Integrations

Add bounded adapters only after the internal model is stable.

Each adapter must:

Start with fake adapters for boundary tests.


Phase 15 — Analytics and Evolution

Build deterministic observation first:

Observe
  ↓
Understand
  ↓
Suggest
  ↓
Approve
  ↓
Implement
  ↓
Measure

A suggestion must remain distinct from an implemented change.

AI can later assist analysis, but the evolution mechanism must remain understandable without AI.


Phase 16 — Optional AI Boundary

Only after deterministic operation works.

AI adapters may provide:

AI output must enter the normal validation/authority/approval path.

No AI provider becomes a foundational runtime dependency.


Historical v2.0 Dependency-Ordered Build Backlog

The following is the implementation sequence. Each item should be treated as a small, bounded engineering task rather than a request to build an entire phase in one pass.

| ID | Task | Depends on | |---|---|---| | IDY-001 | Repository audit against this plan | — | | IDY-002 | Establish No Composer; native autoloading / PSR-4-style namespaces | IDY-001 | | IDY-003 | Create App\\Runtime composition root | IDY-002 | | IDY-004 | Establish runtime configuration boundary | IDY-003 | | IDY-005 | Establish PDO + pdo_mysql connection factory | IDY-004 | | IDY-006 | Establish migration mechanism | IDY-005 | | IDY-007 | Establish PHPUnit 11 | IDY-002 | | IDY-008 | Establish HTTP/request/response boundary | IDY-003 | | IDY-010 | User/credentials persistence (legacy Type name Principal) | IDY-006 | | IDY-011 | Login/logout/session lifecycle | IDY-010 | | IDY-012 | CSRF/rate limiting/security middleware | IDY-011 | | IDY-013 | Business object foundation | IDY-006 | | IDY-014 | Membership object | IDY-013 | | IDY-015 | AuthorityGrant object | IDY-014 | | IDY-016 | Business context resolver | IDY-015 | | IDY-017 | Authentication/Business isolation tests | IDY-016 | | IDY-020 | objects table | IDY-006 | | IDY-021 | object_revisions table | IDY-020 | | IDY-022 | Object repository | IDY-021 | | IDY-023 | Type definition representation | IDY-020 | | IDY-024 | Type revision representation | IDY-023 | | IDY-025 | Typed value validator | IDY-024 | | IDY-026 | Object retrieval service | IDY-022, IDY-025 | | IDY-027 | Expected-version mutation primitive | IDY-022 | | IDY-028 | Object revision/history tests | IDY-027 | | IDY-030 | Command canonicalization | IDY-027 | | IDY-031 | Command fingerprinting | IDY-030 | | IDY-032 | command_keys | IDY-031 | | IDY-033 | Command/Action/Attempt objects | IDY-032 | | IDY-034 | Command admission transaction | IDY-033 | | IDY-035 | Command commit transaction | IDY-034 | | IDY-036 | Duplicate/stale/unknown handling | IDY-035 | | IDY-037 | /commands endpoint | IDY-036 | | IDY-038 | Command concurrency tests | IDY-037 | | IDY-040 | State definitions | IDY-025 | | IDY-041 | State transitions | IDY-040 | | IDY-042 | Transition occurrence/history | IDY-041 | | IDY-043 | Effective/recorded time support | IDY-042 | | IDY-045 | History conformance tests | IDY-043 | | IDY-050 | Relationship Type | IDY-024 | | IDY-051 | Relationship object | IDY-050 | | IDY-052 | Relationship validator | IDY-051 | | IDY-053 | Relationship index | IDY-052 | | IDY-054 | Relationship navigation | IDY-053 | | IDY-055 | Relationship authorization | IDY-054, IDY-015 | | IDY-056 | Graph/isolation tests | IDY-055 | | IDY-060 | Policy object | IDY-024 | | IDY-061 | Allowlisted policy expression evaluator | IDY-060 | | IDY-062 | Policy composition | IDY-061 | | IDY-063 | Decision object/review | IDY-062 | | IDY-064 | Commit-time authority/policy recheck | IDY-063, IDY-035 | | IDY-065 | Policy conflict tests | IDY-064 | | IDY-070 | View Definition | IDY-024 | | IDY-071 | Renderer registry | IDY-070 | | IDY-072 | Application shell | IDY-071, IDY-016 | | IDY-073 | Login UI | IDY-072 | | IDY-074 | Business selector | IDY-073 | | IDY-075 | Object list/detail | IDY-074, IDY-026 | | IDY-076 | Operation forms | IDY-075, IDY-037 | | IDY-077 | Command status UI | IDY-076 | | IDY-078 | History/provenance UI | IDY-077 | | IDY-080 | Genesis manifest format | IDY-064, IDY-070 | | IDY-081 | Bootstrap CLI | IDY-080 | | IDY-082 | Idiosyncrasy seed data | IDY-081 | | IDY-083 | Genesis idempotency/conflict handling | IDY-082 | | IDY-085 | Workflow Definition representation | IDY-024 | | IDY-086 | Workflow Execution representation | IDY-085 | | IDY-087 | Sequential interpreter | IDY-086 | | IDY-088 | Condition node | IDY-087, IDY-061 | | IDY-089 | Local mutation Action | IDY-087, IDY-037 | | IDY-090 | Approval node | IDY-089, IDY-063 | | IDY-091 | Wait node | IDY-090 | | IDY-092 | Dispatcher/lease | IDY-091 | | IDY-093 | Resume/reconciliation | IDY-092 | | IDY-094 | Workflow execution tests | IDY-093 | | IDY-100 | Spearmint Business configuration | IDY-083, IDY-056 | | IDY-101 | Enquiry type/configuration | IDY-100 | | IDY-102 | Qualification type/Decision Policy | IDY-101 | | IDY-103 | Project/relationship configuration | IDY-102 | | IDY-104 | Spearmint bounded workflow | IDY-103, IDY-094 | | IDY-105 | Spearmint UI views/forms | IDY-104, IDY-078 | | IDY-106 | Demonstrator acceptance suite | IDY-105 | | IDY-110 | Structured retrieval service | IDY-056, IDY-026 | | IDY-111 | Permission-aware retrieval | IDY-110, IDY-064 | | IDY-112 | Knowledge/source objects | IDY-111 | | IDY-113 | Knowledge applicability | IDY-112 | | IDY-114 | Knowledge retrieval tests | IDY-113 | | IDY-120 | Content foundation | IDY-070 | | IDY-121 | Communication foundation | IDY-037, IDY-120 | | IDY-122 | Fake external adapter | IDY-121 | | IDY-123 | Adapter attempt/outcome handling | IDY-122 | | IDY-130 | Analytics observations | IDY-106 | | IDY-131 | Suggestion object/evidence | IDY-130 | | IDY-132 | Review/approval of suggestion | IDY-131 | | IDY-133 | Measurement outcome | IDY-132 | | IDY-140 | AI provider abstraction | IDY-114 | | IDY-141 | AI proposal validation | IDY-140 | | IDY-142 | AI authority/approval boundary | IDY-141 | | IDY-143 | AI-disabled conformance suite | IDY-142 |

The IDs are planning identifiers, not new architecture decision numbers.


25. Reference Acceptance Inventory (Status Owns Evidence)

The first demonstrator is complete only when all of the following are true:


26. What Must Not Be Built Yet

Do not allow implementation drift into:

A feature belongs in the runtime only if it can be expressed through the approved model or introduces genuinely reusable execution behaviour under the product's composition rules.


27. Engineering Rule for New Requirements

Before adding code, ask:

1. Can this be represented by an existing Type? 2. If not, can it be represented by a new Type and configuration? 3. Can existing Relationships express it? 4. Can an existing Workflow/Action express the behaviour? 5. Can an existing View/Content mechanism present it? 6. Can an existing Policy express the authority rule? 7. Can an existing engine/responsibility execute it? 8. Does it genuinely require new reusable execution behaviour? 9. Does that new behaviour preserve the universal object model? 10. Does it remain useful with AI disabled?

Only the final question supports a genuinely new execution responsibility.


28. Copilot/Luna Task Protocol

Each implementation task should contain:

TASK ID

Objective:
What single outcome must exist when this task is complete?

Canonical owner:
Which Idiosyncrasy document owns the meaning?

Dependencies:
Which prior tasks must already exist?

Allowed scope:
Which files/components may be changed?

Required mechanism:
What does the implementation architecture require?

Contracts:
What interfaces/data/API behaviour must remain stable?

Tests:
What focused evidence must be added or run?

Acceptance:
What observable behaviour proves completion?

Definition of done:
What must be true before the task is considered complete?

Luna/Copilot must not silently redesign architecture while implementing a task.

If a genuine conflict with the current documentation is discovered:

1. stop the affected implementation slice; 2. identify the canonical document; 3. describe the conflict; 4. do not invent a new architecture decision number; 5. request owner review where the conflict cannot be resolved by the existing specification.

Routine implementation detail does not require a new D-number.


29. First Luna/Copilot Instruction

The following is historical onboarding text retained for traceability. It is not an active task instruction; use the current task, canonical owners, implementation contracts, development guidance and status instead.

Read the relevant current Idiosyncrasy documentation and the applicable section of docs/implementation/implementation-plan.md before changing application code. Do not load this planning document in full by default.

The documentation is authoritative. Treat D01-D10 as settled. Do not redesign the product into a conventional SaaS/CRM architecture.

Your task is repository assessment only.

Compare the current repository against the implementation plan and report:

1. what already exists and can safely be reused;
2. what is legacy and must remain outside the new runtime;
3. what implementation mechanisms are missing;
4. any direct conflicts between repository code and the current specification;
5. the smallest dependency-ordered implementation task that should be done first;
6. the tests/evidence that task requires.

Do not implement anything yet.

Preserve these non-negotiable properties:
- universal id + type + value model;
- one Business Graph;
- first-class addressable Types;
- explicit relationships;
- explicit authority and Policy;
- independent Business identity and Business-scoped isolation;
- Command-centred mutation;
- durable versions and history;
- deterministic workflows;
- explicit Unknown/Reconciliation;
- model-projection UI;
- AI optionality;
- structured-first retrieval;
- readable/editable/versionable configuration;
- no arbitrary runtime code generation;
- modular monolith;
- PHP 8.3.33;
- MariaDB 10.5.26/InnoDB;
- no application framework;
- no Composer;
- first-party native autoloader with PSR-4-style namespaces;
- Spearmint Design as the first demonstrator.

Do not create new architecture decisions merely because code is missing. The implementation specification already selects the smallest conforming mechanisms.

End with a proposed first implementation task using the task protocol in the implementation plan.

30. Superseded Build Sequence Summary (Traceability Only)

DOCUMENTATION
    ↓
Repository audit
    ↓
No-Composer runtime foundation
    ↓
Authentication + Business context
    ↓
Universal objects + Types
    ↓
Command pipeline
    ↓
State + History
    ↓
Relationships
    ↓
Authority + Policy
    ↓
Model-driven UI
    ↓
Controlled Genesis
    ↓
Workflow runtime
    ↓
Spearmint configuration
    ↓
Spearmint Enquiry
    ↓
Qualification
    ↓
Project / Scoping
    ↓
Architecture acceptance gates
    ↓
Knowledge + Retrieval
    ↓
Content / Communication
    ↓
Integrations
    ↓
Analytics / Evolution
    ↓
Optional AI

The first major proof is therefore not “Idiosyncrasy has lots of features”.

It is:

> Spearmint Design can be represented and operated by the generic runtime, and a new business concept can be introduced through types/configuration rather than bespoke application/database code.


31. Source Traceability

This plan is derived from the current live documentation structure at:

https://docs.idiosyncrasy.co.uk/docs/

Key implementation decisions are owned by:


32. Final Principle

Idiosyncrasy is not being implemented as a collection of applications with a common login.

It is being implemented as a generic business runtime in which applications are projections of a shared, addressable, governed business model.

The implementation must therefore optimise for:

semantic integrity → reusable runtime behaviour → deterministic execution → human operation → demonstrable business value → optional intelligence

not:

feature count → bespoke modules → AI generation → infrastructure complexity.

The first implementation should be deliberately small, but it must be structurally faithful to the architecture.