D057 — Unattended installer profile

D057 — Unattended installer profile

Canonical path: C:\Users\Administrator\Desktop\Storage\Projects\The Grand Project\decisions.md

Current revision: REV-2C31DC8D04A54918

View Diff

D057 — Unattended installer profile

The unattended installer is driven by a validated JSON install profile with explicit application, database, administrator, secrets, and selected-plugin sections. That keeps config-driven installs deterministic and lets the same shared installer readiness report back both text and JSON output without duplicating validation rules.

D056 — CLI installer entrypoint

The CLI installer lives at the repository root under `install/install.php` and delegates to the shared installer report. A sibling `install/checks.php` helper returns the same readiness data so terminal installation flows can stay in sync with the web installer without duplicating checks.

D055 — Web installer root detection

The web installer evaluates the project root derived from the framework bootstrap path, not the framework subdirectory itself. That keeps readiness checks aligned with the actual install surface, including the root-level `recovery/` folder and other project-level writable paths.

D054 — Feature flags

Feature flags are implemented as a framework-native in-memory service with installation, company, and user scopes. Resolution uses the most specific matching scope first: user, then company, then installation, so rollout controls remain predictable for gradual releases and targeted disablement.

D053 — Secrets service

The secrets service is implemented as a provider-backed framework abstraction rather than a config helper. Local storage uses AES-256-GCM with a required master key, logical-key lookup, and versioned immutable records so secret values stay encrypted at rest while future external secret providers can implement the same contract.

D051 — Audit service

The audit service is implemented as an append-only framework layer on top of the structured logger. It keeps business and security state changes in immutable audit records, and it applies the same sensitive-data redaction rules before persisting or logging audit metadata.

D052 — Deterministic retention checks

`FileService::upload` accepts an optional explicit timestamp so storage retention can be tested deterministically without depending on the host clock. The smoke test now passes the same baseline time through upload, temporary URL verification, and delete checks.

decisions.md

D105 - ServiceVault / Asset Registry boundary is authoritative and degradable

Asset Registry owns the physical world: location identity, asset identity, QR authority, commissioning, manuals, reference photos, and physical history references. ServiceVault owns the servicing of that world: service records, measurements, reports, attachments, and technician workflows. ServiceVault may integrate with Asset Registry through capability discovery and runtime events, but it must still boot and operate in a degraded mode when Asset Registry is absent or disabled, and it must not recreate legacy physical ServiceVault tables as a fallback.

D106 - Inventory Tracking operational foundation is warehouse-led and ledger-backed

Inventory Tracking's first usable runtime foundation is warehouse-led stock balancing and transfer handling, not broad inventory lifecycle coverage. Warehouses are company-scoped and code-addressable, stock is tracked as on-hand and available quantities per product and warehouse, movement history is append-only, and warehouse transfers must complete atomically through the repository transaction boundary. Quantities are normalized to four decimal places so the live balance model stays deterministic without introducing count, receiving, returns, adjustment, or valuation behavior ahead of its boundary.

D092 - Explicit endpoint bootstrap

Generated deployment entrypoints are tiny managed `index.php` shims that set explicit endpoint identity in environment variables and then load a colocated sidecar bootstrap configuration file containing the authoritative shared bootstrap path. Normal operation must not require a mandatory `GRAND_PROJECT_BOOTSTRAP` server environment variable, although an environment-variable override may remain available as an optional escape hatch. That removes hostname discovery as a requirement for deployed auth, admin, and Website Builder entrypoints and avoids baking secrets or hard-coded framework paths into every generated site file.

D093 - Endpoint deployment safety

Endpoint deployment is deny-by-default on filesystem scope: Local Web Roots must be in an allowlisted path, must be writable, and must not already belong to another registered endpoint. Unmanaged existing `index.php` files are never silently overwritten; replacement requires explicit approval and the prior file is backed up before the managed entrypoint is written.

D101 - Installation profiles are presets over manifests

Installer installation profiles are convenience presets, not a second dependency system. A selected profile contributes requested and optional Plugin Modules plus endpoint recommendations, then the authoritative `plugin.json` manifests drive dependency addition, conflict detection, version checks, installation order, and final migration selection. Unselected modules remain discovered but inactive, and auth-only installs must not create unrelated business tables simply because those modules ship in the deployment archive.

D102 - Installation Type is the top-level deployment role

The first authoritative installer choice is the installation type, not the business/application profile. `auth-server`, `update-server`, and `file-server` represent central Grand Project server roles; `general` represents a normal application install that may then choose a General-only application profile such as ServiceVault, Commerce Website, or Custom.

D103 - Central services split server and client capability

Central Authentication, Update Server, and File Server responsibilities are separated into explicit server and client capabilities. Normal General installations must consume central services through client capability and configuration rather than installing the central server implementation, while dedicated central-service deployments expose registry/API/admin surfaces for their own role only.

D104 - General central authentication uses application sessions

When a General installation is configured to use the central Authentication Server, the local runtime may establish its authenticated context from the application-session cookie created by the SSO callback flow. That avoids requiring a local auth session cookie on every General install while preserving local permission evaluation, company context, and admin access control.

decisions.md

D091 — Business Intelligence & Reporting module foundation

The BI & Reporting implementation is a real top-level plugin module with the `bir_` table prefix and no hard dependencies. The batch covers dashboards, KPIs, authorised analytical views, reporting, and exports while preserving the rule that derived analytical data is not authoritative over source plugins.

D090 — Supplier Portal module foundation

The Supplier Portal implementation is a real top-level plugin module with the `spl_` table prefix and a required dependency on Suppliers. The batch covers supplier records, catalogues, products, documents, purchasing interactions, and communications without inventing extra commerce responsibilities or loosening the supplier boundary.

D089 — Partner Portal module foundation

The Partner Portal implementation is a real top-level plugin module with the `par_` table prefix and no hard dependencies. The batch covers partner, distributor, and reseller-facing access based on role and relationship, plus document and communication surfaces, while keeping the portal boundary separate from Supplier Portal and the later commerce stack.

D088 — OpsRoom module foundation

The OpsRoom implementation is a real top-level plugin module with the `ops_` table prefix and no hard dependencies. The batch covers projects, procedures, documents, internal workflows, business knowledge, and management tools, while keeping Tendering outside the module boundary exactly as the specification requires.

D087 — Developer Platform module foundation

The Developer Platform implementation is a real top-level plugin module with the `dev_` table prefix and no hard dependencies, matching the spec's minimal-dependency stance for developer tooling. The batch covers scaffolding, diagnostics, migrations, test support, deployment utilities, documentation, plugin validation, and contract testing without turning the tooling surface into a general-purpose platform service.

D086 — Order Processing module foundation

The Order Processing implementation is a real top-level plugin module with the `ord_` table prefix and a required dependency on Inventory Tracking. The batch covers allocation, fulfilment, picking, packing, dispatch, completion, cancellation, and recovery states without collapsing into the upstream inventory ownership boundary or inventing extra commerce responsibilities.

D085 — Inventory Tracking module foundation

The Inventory Tracking implementation is a real top-level plugin module with the `inv_` table prefix and a required dependency on Products. The batch currently covers stock, warehouses, stores, bin locations, vehicles, transfers, and movement history without collapsing into the later Order Processing boundary, while receipts, allocations, returns, adjustments, serials, batches/lots, reorder levels, stocktakes, and valuation remain deferred scaffolding rather than advertised runtime surface.

D084 — Suppliers module foundation

The Suppliers implementation is a real top-level plugin module with the `sup_` table prefix and an optional/recommended integration with Products. The batch covers supplier records, contacts, terms, lead times, catalogues, preferred-supplier status, purchasing information, and supplier/product relationships without inventing extra module boundaries or hard dependencies.

D083 — ServiceVault module foundation

The ServiceVault implementation is a real top-level plugin module with the `svc_` table prefix and a required dependency on Asset Registry. The internal customer and technician portals are represented as nested module folders under ServiceVault so the portal boundary exists without turning them into standalone top-level plugin modules. Optional integrations remain optional and do not become hard dependencies.

D082 — Asset Registry module foundation

The Asset Registry implementation is a real top-level plugin module with the `ar_` table prefix and a data model that covers assets, asset types, specifications, properties, locations, relationships, lifecycle events, maintenance, warranties, manuals, documents, QR identifiers, and equipment knowledge. The asset-class plugin architecture is represented as an internal catalog plus an `asset-classes/Pool` reference package so the first specialised class implementation exists without splitting the module boundary into a new top-level plugin.

D067 — Updates administration surface

The administration Updates page is a read-only operator surface built on the existing release manager, update client, and restore-point manager. It summarizes the staged/current/previous release slots, the current update plan from the same metadata format used by the CLI client, and the backup preflight state so operators can review update readiness without duplicating release logic in the admin layer.

D066 — Dependency visualiser graph source

The dependency visualiser is manifest-driven and reads relationships from `plugin.json` rather than from a separate admin-maintained graph store. Required, optional, recommended, and conflicting edges are all shown in the admin view, and missing targets are treated as visible warnings so operators can see the dependency gap without conflating it with a runtime failure.

D065 — Plugin manager manifests and dependency map

The administration plugin manager is manifest-driven: it inventories plugin module directories, validates `plugin.json`, and renders module details from the manifest rather than from separate admin-specific records. The dependency map shown in the admin UI is generated from the manifest `dependencies.required` list so operators see the same dependency truth that the plugin runtime consumes.

D064 — Administration health dashboard base paths

The administration health dashboard is rooted at the repository-level `administration/health.php` entrypoint, but it bootstraps the Common Application Framework from `Core Platform/Common Application Framework/`. The dashboard service treats the framework directory as the installer base path and derives the project root separately so framework readiness checks, restore-point discovery, plugin discovery, and storage checks all evaluate the correct filesystem surface.

D001 — Plugin categorisation

All installable applications are called **Plugin Modules** and live under `Plugin Modules/`. Do not use separate “foundational” and “business” plugin categories.

D002 — Core System Services

Infrastructure service plugins live under `Core System Services/`:

- Update Server

- Backup / Restore Server

- Storage Server

- Analytics Server

D003 — ServiceVault portals

Customer Portal and Technician Portal are internal modules of ServiceVault, not standalone Plugin Modules.

D004 — ServiceVault dependency

ServiceVault requires Asset Registry.

D005 — Tendering

Tendering is not part of OpsRoom. Project Tendering is its own Plugin Module.

D006 — Sales module naming

Sales Floor was renamed to **Lead Pipeline**.

D007 — Lead Pipeline supplier relationship

Lead Pipeline does not require Suppliers. Suppliers integration is optional.

D008 — Product/inventory/order chain

Products is authoritative for the product catalogue.

Inventory Tracking requires Products.

Order Processing requires Inventory Tracking.

D009 — E-commerce dependencies

E-commerce requires:

- Products

- Suppliers

- Payments & Billing

- Invoice Generation

Inventory Tracking, Order Processing and Website Builder are optional E-commerce integrations.

D010 — Payments

Payments & Billing requires Invoice Generation and supports Stripe, PayPal, future payment providers and Xero API accounting integration.

D011 — Account model

One user account can simultaneously hold customer, supplier, partner, technician, employee and other authorised relationships.

D012 — Data ownership

Each business record has one authoritative owning plugin. Cross-plugin direct database access is prohibited.

D013 — Plugin manifests

All hard dependencies, capabilities, version requirements, permissions, migrations and lifecycle metadata are declared in `plugin.json`.

D014 — Updates

No framework/plugin update proceeds without a valid pre-update restore point.

D015 — Historical records

Use reference + snapshot where historical accuracy matters.

D016 — AI access

AI agents use approved tools/scopes through the same authorisation architecture and do not receive unrestricted database access.

D017 — Canonical empty folders

Canonical empty project folders are kept versionable with `.gitkeep` placeholders until the corresponding framework or plugin files are added.

D018 — Local bootstrap autoloader

The framework bootstrap includes a local PSR-4 autoloader fallback so the project can bootstrap before Composer dependencies are installed. Composer remains the canonical package manager and the root `composer.json` is the authoritative package definition.

D019 — Baseline CI scope

The first CI pass validates the Composer manifest and PHP syntax before introducing package-installed analysis tools. This keeps the initial pipeline lightweight while the framework surface area is still small.

D020 — Repository root documentation

The authoritative master specification and supporting handover records are mirrored into the repository root so active implementation work can reference them without leaving the project tree.

D021 — Environment and config loading

The framework bootstrap loads project environment variables from a local `.env` file when present, but it does not overwrite already-defined environment values. Configuration is loaded through a dedicated loader and accessed through dot-notation keys on the `Application` object.

D022 — Request/response abstractions

The framework request object is immutable and represents method, URI, path, headers, query data, body content and attributes. The response object is immutable as well and supports plain text and JSON helpers for the later router and middleware phases.

D023 - Router and middleware pipeline

The framework router uses exact-match method/path registration with a 404 fallback for unmatched routes. Middleware is executed in registration order around route handlers, and middleware plus handlers must return framework Response objects so the dispatch contract stays consistent.

D024 — Database abstraction

The framework database layer exposes a connection interface with PDO and in-memory implementations. The in-memory adapter exists so the abstraction can be verified in environments without a local PDO driver, while the PDO adapter remains the production path.

D025 — Local PDO driver enablement

The local Windows PHP CLI was configured with `pdo_sqlite` and `sqlite3` enabled so the database abstraction could be verified against a real PDO driver in this environment.

D026 — Request and correlation IDs

The HTTP request object owns a request ID and a correlation ID. Incoming request headers are honored when present, and generated identifiers are used otherwise so logs and later middleware can share the same request context.

D027 - Central Authentication integration contract

The framework owns the central authentication integration contract rather than any plugin. The contract is represented as a gateway interface plus immutable value objects for identities, sessions, service credentials and service health.

D028 — User context

The framework owns a dedicated user context object for request-scoped identity data. It is built from the central authentication contract and carries authenticated identity details, session linkage and request identifiers, while keeping company/relationship resolution for a later phase.

D029 — Company and relationship context

The framework owns the company/relationship context as request-scoped identity state. It tracks the active company, related company records and relationship records, while leaving role and policy resolution for later phases.

D030 — Roles

The framework owns role context separately from permissions. Roles are represented as records and assignments that can be global or company-scoped, with request-scoped resolution based on the authenticated user and company context.

D031 — Permissions

The framework owns permission context separately from roles. Permissions are represented as records and grants that can be global or company-scoped, with request-scoped resolution layered on top of identity, role and company context.

D032 — Record policies

The framework owns record policy context separately from permissions. Record policies are represented as records and grants that can be global or company-scoped, with request-scoped resolution layered on top of identity, role, company and target-record context.

D033 — Service identities

The framework owns service identity context separately from human authentication. Service identities are represented as scoped identity records with explicit credential linkage, and service credentials track issuance plus rotation lineage so API requests can be authenticated and renewed without changing the security model.

D034 — Plugin manifest schema

The canonical `plugin.json` schema lives in the Common Application Framework as a reusable shared asset. It defines the required manifest structure from the master specification while allowing future manifest extensions without forcing a schema redesign.

D035 — Manifest validator

Plugin manifest validation is implemented in the Common Application Framework as a framework-native validator that checks the canonical required fields, nested lifecycle sections, and dependency shape before plugin runtime work consumes the manifest.

D036 — Plugin discovery

Plugin discovery scans immediate plugin module directories, validates each `plugin.json` through the manifest validator, and reports per-module errors without hiding successful discoveries from sibling folders.

D037 — Plugin registry

The plugin registry is an in-memory authoritative store for discovered modules and their lifecycle state. Registry entries are immutable snapshots that can be promoted through lifecycle statuses so later install and enable/disable work can build on a single source of truth.

D038 — Dependency resolver

Dependency resolution is handled in the Common Application Framework from registry entries and manifest data. The resolver validates framework compatibility, required dependency presence and status, conflicts, and circular graphs before later lifecycle code consumes an install order.

D039 — Capability registry

Capability registration is derived from plugin manifests and the registry state. The Common Application Framework keeps an in-memory capability index keyed by declared `provides` entries so later lifecycle and dependency checks can ask which enabled plugin supplies a given capability.

D040 — Install lifecycle

Install lifecycle is handled as a registry state transition from discovered to installed after dependency preflight succeeds. Installation does not implicitly enable a plugin; it records the installed state and leaves activation to the enable/disable lifecycle.

D041 — Enable/disable lifecycle and reverse-dependency guard

Plugin activation and deactivation are handled by the Common Application Framework lifecycle manager. Enable flows only promote installed plugins after dependency resolution succeeds, and disable flows refuse to deactivate any plugin that still has enabled reverse dependents. Smoke coverage captures the registry state immediately after the failed disable attempt so later cleanup steps do not invalidate the assertion.

D042 — Dependency lock file

The Common Application Framework maintains an in-memory dependency lock snapshot alongside the plugin registry. The lock stores exact installed plugin versions, package names, lifecycle status and timestamps, and the installer plus lifecycle manager refresh it after state transitions so the snapshot remains aligned with the authoritative registry.

D043 — Events/outbox

Important asynchronous events are handled through a durable transactional outbox in the Common Application Framework. Events are captured as envelopes with source, correlation and payload metadata, persisted through the database abstraction, and can be claimed, dispatched, released or replayed without turning events into imperative commands.

D044 — Queue/workers

Shared queue and worker behavior is implemented as an in-memory Common Application Framework service for now. Jobs carry priorities, scheduled availability, retry and dead-letter metadata, idempotency keys, and progress state, while workers consume registered handlers and move jobs through queued, processing, completed, canceled, retry and dead-letter states.

D045 — Scheduler/locks

The Common Application Framework scheduler owns task execution and uses explicit per-task locks to prevent duplicate scheduled runs. Scheduled task records track the latest run state, next run time, and execution metadata, while the lock registry can be snapshotted and reloaded alongside the scheduler state.

D046 — Workflow/saga engine

Cross-plugin business processes are modeled as saga-style workflows in the Common Application Framework. Workflow steps are executed in order, step history is captured for administration, and compensating actions run in reverse order when a later step fails so the workflow remains inspectable and recoverable without relying on giant SQL transactions.

D047 — Storage abstraction

Shared storage is implemented as a provider-backed abstraction in the Common Application Framework rather than a plugin-specific file helper. The batch establishes file identity, safe filename generation, versioning, retention, visibility, metadata, and signed temporary URLs in the framework layer so the later file service can build on one consistent contract for local and future remote backends.

D048 — File service

The file service sits on top of the storage abstraction and uses the existing authentication contracts to enforce company boundaries, owner metadata, permissions, and record policies. Public files remain readable without extra checks, while private file access and lifecycle operations flow through the same framework-level service so later plugin modules can consume one shared upload/download API.

D049 — PDF/document service

The document engine is implemented as a framework service layered over storage so rendered outputs become immutable historical snapshots with template version and checksum metadata. Instead of relying on an unavailable external PDF runtime, the service includes a deterministic internal PDF writer for batch-safe output while still supporting HTML renders, branding, headers, footers, attachments, numbering, and revision tracking through the shared document contract.

D050 — Notifications/email

Notifications are implemented as a shared framework service with channel preferences, in-app notices, and queued email delivery rather than as plugin-owned mail logic. The email layer keeps sender identities, templates, attachments, delivery records, and development capture in the Common Application Framework so mandatory security notifications can bypass suppression rules and retryable deliveries can be processed through a single reusable contract.

D058 — Update client planning

The update client is a framework-owned planning surface that reuses plugin dependency resolution to produce a dependency-ordered update plan before any package is applied. Update planning must not proceed when the release metadata is incomplete for the target registry, and the plan surface exposes both text and JSON output so the same contract can drive future operator and automation entrypoints.

D059 — Signed update packages

Signed update packages are verified against the downloaded package artifact with checksum validation and an RSA signature over the package bytes. The smoke test generates its own temporary OpenSSL config because the Windows PHP runtime in this environment lacks a usable default `openssl.cnf` path, but the production verifier still depends on real OpenSSL signature checks rather than a mocked checksum-only shortcut.

D060 — Controlled release slot switching

Update deployment uses isolated staging/current/previous directories so release promotion happens by whole-directory rotation instead of piecemeal live-file edits. The manager also keeps a rollback path by restoring the prior current release into the previous slot, which gives the later automatic-rollback work a concrete filesystem primitive to reuse.

D061 — Restore-point snapshots

Restore points are implemented as filesystem-backed manifests that capture the framework files, affected plugin files, database snapshot, plugin registry, configuration, migration state, dependency lock, version metadata, checksums and storage metadata reference that the specification requires. The manager exposes list and inspect operations plus status transitions so later rollback and emergency-recovery work can reuse the same snapshot format.

D062 — Automatic rollback coordination

Automatic rollback is implemented as a coordinator over the restore-point manager and release-slot manager. It marks a restore point as restoring, rolls the release directories back to the prior release, can invoke a database-restoration callback when the file rollback alone is not trustworthy, and then marks the restore point restored so critical-failure recovery remains auditable.

D063 — Independent recovery utility

The emergency recovery utility lives under `recovery/` and runs without depending on the normal framework bootstrap. It accepts a local recovery config file, falls back to `recovery/config.json` when present, and uses its own logging plus restore-point inspection so operators can restore files, database snapshots and configuration even when the main runtime is unhealthy.

D071 — Workflow viewer administration surface

The administration Workflow Viewer page is a read-only operator surface built on the workflow history snapshot format. It shows workflow instance status, recent runs, and step history so operators can review saga execution without duplicating workflow logic in the admin layer.

D070 — Scheduler administration surface

The administration Scheduler page is a read-only operator surface built on the in-memory scheduler snapshot format. It shows scheduled task inventory, due and upcoming work, lock registry state, and runtime readiness so operators can review scheduler health without duplicating scheduler logic in the admin layer.

D069 — Queues/jobs administration surface

The administration Queues / Jobs page is a read-only operator surface built on the in-memory queue snapshot format. It shows queue inventory, status counts, worker readiness, and recent job history so operators can review queue health without duplicating worker logic in the admin layer.

D068 — Backup/restore administration surface

The administration Backup / Restore page is a read-only operator surface built on the existing restore-point manager and recovery file layout. It shows restore-point inventory, latest snapshot integrity, recovery utility readiness, log history, and restore target checks so operators can review backup health without duplicating recovery logic in the admin layer.

D072 — Integration manager administration surface

The administration Integration Manager is a read-only operator surface built on the framework's existing authentication, service-credential, request-tracing, queue, webhook, logging, and audit primitives. It reports the current integration contract and delivery posture without introducing a second integration runtime, and it surfaces the absence of a dedicated rate-limiting service as an explicit gap instead of simulating one.

D073 — Credentials administration surface

The administration Credentials page is a read-only operator surface built on the framework's authentication contract, service credential value objects, and session boundary primitives. It reports credential lifecycle support, scoped issuance, rotation lineage, and credential-related redaction without inventing a persistent credential store or weakening the security model.

D074 — AI agents administration surface

The administration AI Agents page is a read-only operator surface built on the framework's AI gateway assumptions, authentication contract, queueing, audit, logging, and file-access primitives. It reports configured providers, agent scopes, approval gates, and safety controls without introducing an unrestricted AI runtime or direct database access path for agents.

D075 — Logs/audit administration surface

The administration Logs / Audit page is a read-only operator surface built on the framework's structured logging, buffered log handler, audit trail, and redaction primitives. It keeps the audit and logging views in the Common Application Framework while deliberately emitting a redacted summary event so the operator surface can prove sensitive fields are scrubbed in buffered output.

D076 — Diagnostics administration surface

The administration Diagnostics page is a read-only operator surface built on the installer readiness report, PHP runtime inspection, configuration snapshot data, and filesystem/tooling checks. It surfaces low-level platform facts without duplicating the installer flow or creating a second mutable diagnostics store.

D077 — Security centre administration surface

The administration Security Centre page is a read-only operator surface built on the framework's authentication, roles, permissions, record policies, encrypted secrets, logging redaction, notification channels, and update policy primitives. It reports the platform's security posture without inventing a separate mutable security store or bypassing the existing framework contracts.

D080 — Products module foundation

The first real business Plugin Module is implemented as `Plugin Modules/Products` with a standalone `prd_` prefix, optional/recommended Suppliers integration, and a minimal catalogue-facing service surface. The initial batch deliberately covers catalogue, SKU, brand, model, variant, specification, document, pricing, and supplier-link metadata plus lifecycle scaffolding, while leaving later Inventory Tracking, E-commerce, and ServiceVault integrations for their own batches.

D081 — Discovery order independence

Plugin discovery smoke tests now treat discovered modules as an unordered set keyed by plugin id rather than assuming the first entry is a specific module. That keeps the Test Plugin contract stable as additional real modules are introduced in `Plugin Modules/` and avoids regressions caused purely by filesystem ordering.

D078 — Test Plugin contract module

The Test Plugin is a deliberately small plugin module that exists to exercise the framework contract before broader plugin development begins. It includes manifest, config, routes, migration, seeder, service, event, job, install, update, rollback, health, and uninstall surfaces so the phase-7 smoke test can prove discovery, lifecycle, capability, lock-file, and release rollback behavior against a real module on disk.

D079 — Test Plugin lifecycle coverage

The phase-7 Test Plugin smoke is treated as the canonical contract test for the plugin runtime. It validates manifest discovery plus install, enable/disable, update promotion, and rollback restoration against the real plugin payload, so the remaining Phase 7 checklist items are satisfied by a single end-to-end lifecycle proof rather than by separate synthetic checks.

D087 — Project Tendering module foundation

The Project Tendering module is implemented as a first-party Plugin Module with its own manifest, navigation, routes, permissions, migration metadata, seed data, lifecycle scripts, and contract smoke test. It remains standalone with only optional integrations to Lead Pipeline, Products, Suppliers, and Invoice Generation so tendering can be deployed without forcing unrelated dependencies.

D086 — Lead Pipeline module foundation

The Lead Pipeline module is implemented as a first-party Plugin Module with its own manifest, navigation, routes, permissions, migration metadata, seed data, lifecycle scripts, and contract smoke test. It is intentionally dependency-light and treats Suppliers, Products, Project Tendering, Invoice Generation, and Order Processing as optional integrations rather than required prerequisites.

D085 — Invoice Generation module foundation

The Invoice Generation module is implemented as a first-party Plugin Module with its own manifest, navigation, routes, permissions, migration metadata, seed data, lifecycle scripts, and contract smoke test. Invoice output is treated as derived from authoritative order and payment records, and the module keeps Payment & Billing and ServiceVault as optional integrations rather than hard dependencies.

D084 — Payments & Billing module foundation

The Payments & Billing module is implemented as a first-party Plugin Module with its own manifest, navigation, routes, permissions, migration metadata, seed data, lifecycle scripts, and contract smoke test. Its manifest declares the spec-mandated required dependency on `Invoice Generation`, while install/lifecycle verification is deferred until that upstream module exists as a real plugin.

D083 — E-commerce module foundation

The E-commerce module is implemented as a first-party Plugin Module with its own manifest, navigation, routes, permissions, migration metadata, seed data, lifecycle scripts, and contract smoke test. Its manifest declares the spec-mandated dependencies on Products, Suppliers, Payments & Billing, and Invoice Generation, while install/lifecycle verification is deferred until those upstream modules are available locally.

D082 — Website Builder module foundation

The Website Builder module is implemented as a first-party Plugin Module with its own manifest, navigation, routes, permissions, migration metadata, seed data, lifecycle scripts, and contract smoke test. Published site content is treated as derived output and must not override source plugin records, which keeps the module inside the spec's website boundary and preserves source-of-truth separation.

D091 — Scaffolded business modules remain preserved but explicitly non-functional

Existing business Plugin Modules beyond Website Builder are preserved with their manifests, lifecycle scripts, migrations, and contract smoke tests intact. Repository status tracking and planning documents now distinguish contract/scaffold completion from genuine functional completion so deferred modules are not misrepresented as production-ready implementations.

D092 — Central Authentication is first-class shared runtime, not a plugin-local shortcut

Authentication for the operational milestone is implemented in the shared framework runtime and reused by Administration and Website Builder. Cross-application login uses exact redirect URI validation and an authorization-code exchange so multiple approved domains and subdomains can participate without weakening the security model through shared insecure cookies or module-specific login shortcuts.

D093 — First operational deployment path uses installer-backed SQLite

The first genuinely usable deployment path is implemented on top of a real SQLite database managed by the Common Application Framework installer. This keeps the milestone small enough to make Central Authentication, Administration, and Website Builder operational immediately, while still exercising real transactions, schema creation, migration tracking, and persistence instead of contract-only schema arrays.

D094 - Active company is the runtime security boundary for the first operational admin path

For the operational Administration plus Website Builder milestone, company-scoped roles and permissions are resolved from the active company membership only. The runtime must not merge privileges from unrelated memberships, and every company switch, site mutation, page mutation, domain assignment, publication event, and application SSO grant is validated against that active-company boundary.

D095 - Cross-domain Grand Project SSO uses local application sessions, not shared auth cookies

The central authentication cookie remains host-local to the auth application. Browser SSO between `auth.localhost` and Grand Project application hosts is implemented through redirect-based authorization code exchange with PKCE and a separate application-local session cookie on the callback host, which preserves browser realism without weakening isolation through a broad shared-domain cookie.

D096 - First production-facing security notifications reuse the shared notification service contract

Password reset and related security-delivery behavior stay inside the Common Application Framework notification and email contract instead of inventing auth-specific mail logic. Local development may still use development capture, but production-style responses must suppress reset-token disclosure and express delivery through the shared notifications path so provider-backed email can be wired in later without changing the auth surface.

D097 - First commerce implementation lives in a framework-owned repository layer

The first real commerce batch is implemented in a dedicated framework `CommerceRepository` instead of duplicating persistence logic across the Product, Supplier, E-commerce, Payments, and Invoice plugin stubs. That keeps the operational runtime aligned with the existing Website Builder and Authentication pattern, centralises schema bootstrap for the first usable deployment path, and gives plugin-facing admin/API routes one authoritative service boundary.

D098 - Storefront visibility is site-scoped and opt-in

E-commerce storefront visibility is controlled per Website Builder site through store configuration rather than by a single global catalogue switch. A site must have its own store record to expose `/shop` routes, and product/category visibility is resolved from that store so multiple sites can share the same framework runtime without leaking catalogue visibility across hosts.

2026-08-12 - Runtime state paths are installation-configurable

- File-backed runtime state for queue snapshots, notifications, scheduler snapshots, scheduler status, scheduler locks, and rate limiting now resolves through administration configuration with environment overrides.

- This keeps the current no-worker, no-CLI hosting path intact while allowing isolated test runs and future per-installation state segregation without hard-coding shared workspace paths.

D099 - Explicit endpoint bootstrap is sidecar-driven, not environment-driven

Generated auth, admin, and website entrypoints are tiny public files that load a colocated sidecar configuration file containing the authoritative framework bootstrap path and install-state path. The supported deployment path must not require a mandatory `GRAND_PROJECT_BOOTSTRAP` server environment variable for normal operation, while an environment-variable override may still exist as an optional escape hatch.

D100 - Deployment package bootstrap must avoid config-time runtime class dependencies

The packaged web bootstrap must tolerate config evaluation before the broader runtime has been constructed. Deployment-critical configuration such as install-state loading therefore must not rely on runtime classes being autoloadable during config-file evaluation; where needed, bootstrap-time config should use direct file decoding or explicit low-level helpers instead.

D106 - ServiceVault technician workflow remains within the physical/service boundary

ServiceVault's first technician workflow phase now covers QR resolution, authorised location lookup, commissioning, service-record lifecycle, measurements, dosing, notes, attachments, review, completion, and customer report generation. Asset Registry remains the authority for physical site, asset, and QR data; ServiceVault persists only service-domain records and reference links, and runtime history references are emitted only from completed ServiceVault persistence.

D107 - Document Generator is shared platform infrastructure, not a business-specific renderer

Document generation now lives behind the common Core document contracts and the first-party Document Generator plugin scaffold. The capability is intended for future plugin consumers and admin surfaces, uses shared storage-backed artifacts and history, keeps administrator template overrides non-destructive to prior snapshots, and only claims PDF support where the existing renderer can genuinely produce it.

Add Bookmark

Add Sticky Note

Add Highlight