24 KiB
Feature Specification: Platform Relocation to apps/platform
Feature Branch: 182-platform-relocation
Created: 2026-04-07
Status: Proposed
Input: User description: "Spec 182 — Laravel Platform Relocation to apps/platform"
Spec Scope Fields (mandatory)
- Scope: workspace
- Primary Routes:
//admin/admin/t/{tenant}/.../system/livewire/*- existing public asset and build entrypoints served through the platform app
public/directory
- Data Ownership:
- No workspace-owned or tenant-owned product tables change ownership in this spec.
- The repo root becomes the source of truth for repo-wide metadata, docs, specs, scripts, editor settings, and orchestration files.
apps/platformbecomes the source of truth for Laravel runtime, application code, tests, build inputs, and app-local environment files.- Existing application data, snapshots, runs, findings, audits, and tenant-scoped artifacts remain owned by their current domains.
- RBAC:
- No new RBAC model, role semantics, capability registry entries, or authorization planes are introduced.
- Existing
/admin,/admin/t/{tenant}/..., and/systemauthorization behavior must remain unchanged after the move. - Non-members remain
404, in-scope capability denials remain403, and the move must not widen route visibility or global search exposure.
For canonical-view specs, the spec MUST define:
- Default filter behavior when tenant-context is active: Not changed by this relocation. Existing tenant-context and canonical-view filters must behave identically before and after the move.
- Explicit entitlement checks preventing cross-tenant leakage: Relocated entrypoints must preserve the existing server-side workspace and tenant entitlement checks exactly; the move must not create alternate paths, stale route bindings, or asset-linked leaks that bypass current
404and403behavior.
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: No
- New persisted entity/table/artifact?: No
- New abstraction?: No new platform abstraction layer, shared package, or workspace engine. The only new contract is an explicit file-placement and command-model decision for the existing app.
- New enum/state/reason family?: No
- New cross-domain UI framework/taxonomy?: No
- Current operator problem: The repo root currently conflates Laravel app root, repo root, tooling root, and documentation root, which makes future multi-app growth and current-day runtime ownership harder to reason about.
- Existing structure is insufficient because: Root-based Laravel assumes that every runtime, script, task, and doc lives in the same top-level namespace. That blocks a clean repo-level topology and makes future additional surfaces harder without first untangling ownership.
- Narrowest correct implementation: Move only the existing Laravel platform app into
apps/platform, update runtime paths and repo tooling to match, and defer website apps, shared packages, workspace orchestrators, and CI/CD redesign. - Ownership cost: The repo takes on one large path migration, documentation updates, task and agent config updates, smoke validation, and clearer rollback expectations for open branches.
- Alternative intentionally rejected: Introducing
apps/website, sharedpackages/, pnpm or Turbo or Nx orchestration, or a CI/CD rebuild in the same slice was rejected as over-scoped and unnecessary for solving the current topology problem. - Release truth: Current-release infrastructure truth with future-facing value. The move prepares later multi-app work without shipping new product behavior in this spec.
Decision Summary
- Official Command Model:
apps/platformis the canonical working directory for platform development. Composer, PHP, Artisan, Sail, Node, Vite, Pint, and test commands are documented and maintained fromapps/platform. Root-level helpers are allowed only as explicit compatibility aids for tools that cannot set a nested working directory cleanly. - Root vs App Placement Matrix: Repo-wide docs, specs, scripts,
.specify, editor configs, agent configs, anddocker-compose.ymlstay at the repo root. Laravel app code, runtime files, tests, build inputs, and app env files live underapps/platform. - Environment Model:
apps/platform/.env.exampleandapps/platform/.envare the canonical Laravel environment files. If a root-level compose env file is required, it is compose-only and must not duplicate or redefine application config truth. - Drizzle and Adjacent Tooling: App-specific database tooling such as
drizzle.config.tsmoves next to the platform app unless a documented repo-wide consumer proves that root placement is necessary. - Root Compatibility Helpers: No second official workflow is allowed. Any retained root wrappers, tasks, or aliases must delegate transparently to
apps/platform, be labeled non-canonical, and remain optional rather than foundational.
User Scenarios & Testing (mandatory)
User Story 1 - Run the Platform From the New Location (Priority: P1)
As a platform developer, I want one official local command model after the move so that I can install dependencies, boot the stack, build assets, and run tests without guessing whether commands belong at the repo root or the app root.
Why this priority: If the command model remains ambiguous, the move fails even if the files are technically relocated.
Independent Test: Can be fully tested by starting from a clean checkout, following the documented local workflow, and reaching a running application plus a passing focused test run without ad-hoc path fixes.
Acceptance Scenarios:
- Given a clean checkout after the move, When a developer follows the documented local setup, Then they can install dependencies, start the stack, and reach the platform app using only the official
apps/platformworkflow. - Given repo-maintained tasks, scripts, and agent instructions, When they invoke platform-local commands, Then they point to
apps/platformor transparently delegate there without inventing a second primary workflow.
User Story 2 - Keep Existing Runtime Surfaces Stable (Priority: P1)
As an operator or maintainer, I want the public entry, admin panels, tenant-scoped panels, system panel, assets, and queue-backed behavior to work the same way after the move so that the relocation does not create a hidden product outage.
Why this priority: Structural success is not meaningful if the relocated app no longer boots or serves the existing product safely.
Independent Test: Can be fully tested by running the smoke pack and confirming that web entrypoints, choose-workspace navigation, a representative tenant-scoped route, preserved 404 versus 403 behavior, Filament panels, assets, and a representative queue-backed flow behave correctly from the relocated app.
Acceptance Scenarios:
- Given the relocated platform app is started through the official workflow, When an operator opens the public root, admin panel, tenant routes, and system panel, Then those surfaces load without asset or bootstrap regressions.
- Given the relocated runtime is active, When a maintainer runs the build and test smoke steps, Then asset manifests, Tailwind scanning, and test bootstrap complete successfully from the new app location.
- Given a queue worker is started under the relocated runtime, When a representative queued flow is executed, Then the worker resolves the app correctly and the flow completes without root-path assumptions.
User Story 3 - Review and Roll Back the Move Safely (Priority: P2)
As a maintainer responsible for a high-churn repo, I want the move to ship with an explicit rollback plan, smoke evidence, and branch-impact guidance so that I can recover quickly if the relocation breaks local or staging workflows.
Why this priority: Large repository moves create merge pressure and hidden environment drift unless rollback and branch guidance are part of the slice.
Independent Test: Can be fully tested by reviewing the documented rollback steps, verifying that they cover local env and artifact cleanup, and confirming that open-branch communication is part of the release notes for the move.
Acceptance Scenarios:
- Given the relocation is ready for review, When a maintainer reads the rollout notes, Then they can see the rollback path, required cleanup steps, and branch-impact guidance without reverse-engineering the diff.
- Given external deployment behavior cannot be proven from the repo alone, When the move is prepared for rollout, Then the unknowns are documented explicitly instead of being silently assumed resolved.
User Story 4 - Keep Repo Tooling Aligned With the New Topology (Priority: P3)
As a contributor using editor tasks, MCP helpers, and repository automation, I want repo tooling to understand the new app location so that path-sensitive helper flows do not lag behind the actual runtime layout.
Why this priority: Tooling drift is a common hidden failure after large topological changes and creates day-two friction even when the app boots.
Independent Test: Can be fully tested by running at least one representative VS Code task or agent or MCP flow and confirming that it resolves the relocated app paths correctly.
Acceptance Scenarios:
- Given repo-maintained tasks and agent configs exist, When one representative task or tool-assisted workflow is executed after the move, Then it resolves the relocated app structure without manual path correction.
Edge Cases
- A hybrid state could leave authoritative Laravel directories both at root and under
apps/platform; the final structure must not require developers to remember which copy is real. - The move could accidentally split
.envtruth between repo root and app root; the spec must prevent two competing application environment locations. - Docker or Sail could start successfully while still mounting the wrong working directory, causing queue workers or asset builds to fail later.
- Asset builds could succeed while
public/index.php, Vite manifest lookup, or Filament asset resolution still points at stale root paths. - Editor tasks, MCP helpers, or agent configs may continue to call root-relative
artisan,phpunit,vite, orvendor/bin/sailpaths after the move. - Open feature branches may become expensive to merge if the move lands without explicit branch and rollback communication.
- Dokploy or production runtime assumptions may differ from local assumptions and must remain visible as unresolved operational follow-up until verified.
Requirements (mandatory)
Constitution alignment (required): This feature introduces no new Microsoft Graph calls, no new product mutations, and no new domain workflow. It changes repository topology and runtime pathing only. Existing contract-registry usage, safety gates, audit logging, tenant isolation, and queued execution flows must continue to work unchanged after the move.
Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001): This feature must remain strictly structural. It may add documentation and repo-local delegation helpers, but it must not introduce shared packages, cross-app abstractions, new persistence, new state families, or speculative monorepo infrastructure.
Constitution alignment (OPS-UX): Existing OperationRun-backed features remain subject to the current Ops-UX contract. The relocation must not change run creation rules, progress surfaces, terminal notification behavior, or service-owned status transitions. Smoke validation must include queue and run-adjacent runtime proof so path changes do not silently break operational observability.
Constitution alignment (RBAC-UX): No authorization behavior changes are allowed. Tenant admin routes, tenant-context routes, workspace-context canonical routes, and system-plane routes must preserve the current 404 versus 403 semantics, server-side enforcement, global-search safety, and destructive-action confirmation requirements.
Constitution alignment (OPS-EX-AUTH-001): Not applicable. This feature does not alter /auth/* handshake behavior.
Constitution alignment (BADGE-001): Not applicable as a feature change. Existing badge semantics must remain unchanged because no operator-facing status model is being redesigned.
Constitution alignment (UI-FIL-001): The feature may touch Filament bootstrap and asset paths, but it must not create new local UI primitives, page-local status markup, or alternate design language. Existing shared Filament usage remains authoritative.
Constitution alignment (UI-NAMING-001): Not applicable as a naming change. Existing operator-facing labels, notifications, and audit prose must remain behaviorally unchanged.
Constitution alignment (UI-CONST-001 / UI-SURF-001 / UI-HARD-001 / UI-EX-001 / UI-REVIEW-001): No new operator-facing surfaces are introduced or reclassified. Existing routes and panels must retain their current canonical nouns, inspect models, and destructive-action placement.
Constitution alignment (OPSURF-001): No operator-surface redesign is part of this spec. If any incidental screen fix is required to preserve runtime after the move, it must preserve the existing page contract rather than using the relocation as a surface redesign opportunity.
Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001): The relocation must not introduce new semantic presenter layers or interpretation frameworks. Validation focuses on observable consequences: commands work, routes boot, panels load, queues run, and docs reflect reality.
Constitution alignment (Filament Action Surfaces): No Action Surface Contract changes are introduced. Existing Filament resources, pages, relation managers, and destructive actions must behave exactly as before once the app runs from apps/platform.
Constitution alignment (UX-001 — Layout & Information Architecture): No screen or layout redesign is part of this spec. Existing layout, empty-state, and infolist or form behavior must remain intact after the move.
Functional Requirements
- FR-182-001: The system MUST relocate the authoritative Laravel application from the repo root to
apps/platform. - FR-182-002: The system MUST not leave an intentional hybrid steady state where core Laravel directories are actively maintained both at the repo root and under
apps/platform. - FR-182-003: The system MUST publish an explicit file-placement contract that distinguishes what stays at the repo root, what moves into
apps/platform, and which exceptions were reviewed deliberately. - FR-182-004: The repo root MUST remain the home for repo-wide docs, specs, scripts, editor config, agent config, and orchestration files after the move.
- FR-182-005:
apps/platformMUST become the home for application code, runtime bootstrap files, tests, build inputs, public entry files, and app-local environment files. - FR-182-006: The official local command model MUST define
apps/platformas the canonical working directory for platform development commands. - FR-182-007: All repo-maintained documentation, tasks, scripts, and helper instructions that describe local platform commands MUST be updated to the canonical command model.
- FR-182-008: Any retained root-level wrapper, alias, or helper MUST delegate transparently to
apps/platform, be documented as non-canonical, and avoid creating a second primary workflow. - FR-182-009:
apps/platform/.env.exampleandapps/platform/.envMUST be the canonical Laravel environment files after the move. - FR-182-010: Any root-level environment file kept for compose or host orchestration MUST be limited to compose-level concerns and MUST NOT become a second source of application configuration truth.
- FR-182-011: App-specific adjacent tooling, including database and local dev helpers such as
drizzle.config.ts, MUST live with the platform app unless a repo-wide consumer is documented explicitly. - FR-182-012: The relocated bootstrap chain MUST continue to resolve correct base paths for
artisan,bootstrap/app.php,bootstrap/providers.php,public/index.php, route registration, config loading, cache paths, and storage paths. - FR-182-013: Composer install, autoload generation, and application class discovery MUST work from
apps/platformwithout manual path patching by developers. - FR-182-014: Vite dev, Vite build, manifest generation, Tailwind source scanning, and public asset resolution MUST work from the relocated app without changing user-facing route structure.
- FR-182-015: Filament admin, tenant, and system panels, including theme resolution and registered assets, MUST render correctly after the move.
- FR-182-016: PHPUnit, Pest, and defined focused or smoke test runs MUST bootstrap successfully from
apps/platform. - FR-182-017: Docker and Sail container mounts, working-directory assumptions, worker commands, and local node-module handling MUST align with the relocated app.
- FR-182-018: Queue workers and at least one representative queued flow MUST start and run correctly under the relocated topology.
- FR-182-019: Repo-level editor tasks, MCP configuration, and agent configuration MUST target
apps/platformexplicitly or delegate there safely. - FR-182-020: The feature MUST include a documented smoke validation pack covering local boot, CLI, build, public entry, panels, auth redirects, workspace-selection navigation, tenant-route authorization semantics including preserved
404versus403behavior, queue, tests, and tooling. - FR-182-021: The feature MUST include a documented rollback path covering git rollback, environment recovery, dependency and build artifact cleanup, Docker state, and communication for open branches.
- FR-182-022: The feature MUST document external deployment unknowns as explicit follow-up questions rather than assuming Dokploy or production behavior from local repo evidence alone.
- FR-182-023: The relocation MUST NOT introduce
apps/website, shared packages, pnpm or Turbo or Nx orchestration, CI/CD redesign, or product feature work in the same slice. - FR-182-024: The relocation MUST preserve existing product behavior, route semantics, authorization behavior, and data ownership behavior.
- FR-182-025: Smoke validation and documentation updates are part of done for this spec and MUST NOT be deferred to follow-up implementation work.
Non-Functional Requirements
- NFR-182-001: The move should remain a single-slice topology change rather than a repo-wide platform rewrite.
- NFR-182-002: The official command model should be understandable from one concise documentation path without mixed primary workflows.
- NFR-182-003: The smoke pack should be runnable on a clean local setup without unpublished shell aliases or private machine knowledge.
Non-Goals
- Creating
apps/website - Introducing a workspace toolchain such as pnpm workspaces, Turbo, Nx, Lerna, or similar orchestration
- Adding shared packages or a new
packages/layer - Rebuilding CI/CD, build-matrix, or deployment architecture in the same slice
- Delivering product features, governance changes, or UI workflow changes unrelated to the move
- Shipping new customer-facing, docs-facing, or API-facing surfaces in this spec
Assumptions
- The existing Laravel application remains the only shipped app in this slice.
docker-compose.ymlremains a repo-level orchestration file after the move.- Future additional apps or surfaces will be addressed in follow-up specs rather than pre-built here.
- Some staging or production runtime details cannot be proven from the repository alone and therefore remain explicit rollout questions.
Dependencies
- Current Docker and Sail setup
- Current Composer, PHP, Vite, Tailwind, and Filament runtime behavior
- Current PHPUnit and Pest bootstrap behavior
- Current repo docs, tasks, scripts, and agent or MCP configuration that reference app paths
Risks
- Docker and Sail may appear to boot while still using stale root working-directory assumptions.
- Hidden root-relative paths in scripts, tasks, or config files may only fail after merge rather than during the first boot.
- Asset output or Filament theme lookup may drift even if the PHP runtime itself boots successfully.
- Open branches may experience high merge friction if the move lands without explicit branch guidance.
- External deployment behavior may differ from local assumptions and must be treated as rollout risk until verified.
External Operational Unknowns
- Actual Dokploy build context after the repo-root or app-root split
- Actual production working-directory expectations for web, queue, and scheduler processes
- Actual storage-volume and persistence mapping expectations outside local Sail
- Any unpublished shell aliases, wrapper scripts, or environment bootstraps currently used by operators or maintainers
Key Entities (include if feature involves data)
- Repo Root: The repo-wide metadata and orchestration layer that remains after the app is moved out of root.
- Platform App: The existing Laravel application relocated to
apps/platform. - File Placement Contract: The documented decision set that assigns each reviewed file or directory to either repo root or app root.
- Official Command Model: The single canonical local workflow for running, building, testing, and maintaining the relocated platform app.
- Environment Model: The explicit separation between application env files in
apps/platformand any optional compose-only env inputs at the repo root. - Smoke Validation Pack: The required cross-runtime checks proving that the relocated topology still boots and behaves correctly.
- Rollback Plan: The documented recovery path for returning local and branch workflows to the pre-move state if needed.
- External Unknowns Register: The explicit list of deployment assumptions that cannot be proven solely from the repository.
Success Criteria (mandatory)
Measurable Outcomes
- SC-182-001: From a clean checkout, a maintainer can follow the documented local workflow and reach a running platform entry surface in 20 minutes or less without needing unpublished path corrections.
- SC-182-002: 100% of repo-documented local platform commands for install, boot, build, format, and test use the canonical
apps/platformworkflow or a clearly labeled delegating helper. - SC-182-003: 100% of the required smoke checks pass on the relocated topology before rollout approval.
- SC-182-004: No authoritative Laravel source directory or app-local manifest remains duplicated between repo root and
apps/platformafter cutover. - SC-182-005: The documented rollback steps let a maintainer restore pre-move local operability, including env and artifact cleanup, in 30 minutes or less on a typical developer machine.
- SC-182-006: 100% of repo-maintained README, handover, task, and agent instructions that reference local platform commands are updated or explicitly deprecated before merge.
- SC-182-007: All external deployment assumptions needed for staging or production rollout are listed explicitly as follow-up questions before rollout approval.
Measurement Protocol
- MP-182-001: Time-based success criteria are measured from the first documented command in
specs/182-platform-relocation/quickstart.mdon a clean local checkout whereapps/platform/.env,apps/platform/vendor/,apps/platform/node_modules/, and app build artifacts are absent before setup begins. - MP-182-002: SC-182-001 stops when the documented CLI smoke passes and
http://localhost/admin/choose-workspacereturns the expected pre-move auth or workspace-selection response. - MP-182-003: SC-182-005 starts at the first documented rollback command and stops when rollback cleanup is complete and the restored local workflow reaches the documented post-rollback sanity state.
- MP-182-004: Timing evidence must record operating system, container runtime, whether Docker images were already available locally, and any intentionally skipped optional smoke steps.