feat: implement workspace foundation website app (#214)
## Summary - add the first multi-app workspace foundation with a new standalone Astro website under `apps/website` - introduce repo-root pnpm workspace orchestration and migrate the platform Node workflow from npm assumptions to pnpm - update root docs, editor or agent guidance, and workspace-focused smoke tests for the new platform plus website command model - add Spec 183 artifacts for spec, plan, research, contracts, quickstart, checklist, and tasks ## Verification - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/WorkspaceFoundation` - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `corepack pnpm build:website` - integrated-browser smoke: verified `http://localhost/up`, `http://localhost/admin/login`, and `http://localhost:4321/` including website anchor navigation and combined root dev flow ## Notes - branch: `183-website-workspace-foundation` - commit: `6d41618d` - root command model now covers `dev:platform`, `dev:website`, `dev`, `build:platform`, and `build:website` - website port override documentation is included in the command contract, quickstart, and README Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #214
This commit is contained in:
parent
ce0615a9c1
commit
03b1beb616
@ -1,5 +1,8 @@
|
||||
node_modules/
|
||||
apps/platform/node_modules/
|
||||
apps/website/node_modules/
|
||||
apps/website/.astro/
|
||||
apps/website/dist/
|
||||
dist/
|
||||
build/
|
||||
vendor/
|
||||
|
||||
27
.github/agents/copilot-instructions.md
vendored
27
.github/agents/copilot-instructions.md
vendored
@ -6,6 +6,8 @@ ## Relocation override
|
||||
- The authoritative Laravel application root is `apps/platform`.
|
||||
- Human-facing commands should use `cd apps/platform && ...`.
|
||||
- Repo-root tooling may delegate via `./scripts/platform-sail` when it cannot set a nested working directory.
|
||||
- Repo-root JavaScript orchestration uses `corepack pnpm install`, `corepack pnpm dev:platform`, `corepack pnpm dev:website`, `corepack pnpm dev`, `corepack pnpm build:website`, and `corepack pnpm build:platform`.
|
||||
- `apps/website` is a standalone Astro app, not a second Laravel runtime, so Boost MCP remains platform-only.
|
||||
- If any generated technology note below conflicts with the current repo, trust `apps/platform/composer.json`, `apps/platform/package.json`, and the live Laravel application metadata over stale generated entries.
|
||||
|
||||
## Active Technologies
|
||||
@ -149,27 +151,44 @@ ## Active Technologies
|
||||
- PostgreSQL with existing tenant-owned `backup_sets`, `backup_items`, and `backup_schedules` records plus existing JSON-backed backup metadata; no schema change planned (180-tenant-backup-health)
|
||||
- PHP 8.4.15, Laravel 12, Blade, Livewire v4, Filament v5.2.x, Tailwind CSS v4, Vite 7 + `laravel/framework`, `filament/filament`, `livewire/livewire`, `laravel/sail`, `laravel-vite-plugin`, `tailwindcss`, `vite`, `pestphp/pest`, `drizzle-kit`, PostgreSQL, Redis, Docker Compose (182-platform-relocation)
|
||||
- PostgreSQL, Redis, filesystem storage under the Laravel app `storage/` tree, plus existing Vite build artifacts in `public/build`; no new database persistence planned (182-platform-relocation)
|
||||
- PHP 8.4.15 and Laravel 12 for `apps/platform`; Node.js 20+ with pnpm 10 workspace tooling; Astro v6 for `apps/website`; Bash and Docker Compose for root orchestration + `laravel/framework`, `filament/filament`, `livewire/livewire`, `laravel/sail`, `vite`, `tailwindcss`, `pnpm` workspaces, Astro, existing `./scripts/platform-sail` wrapper, repo-root Docker Compose (183-website-workspace-foundation)
|
||||
- Existing PostgreSQL, Redis, and filesystem storage for `apps/platform`; static build artifacts for `apps/website`; repository-managed workspace manifests and docs; no new database persistence (183-website-workspace-foundation)
|
||||
|
||||
- PHP 8.4.15 (feat/005-bulk-operations)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```text
|
||||
src/
|
||||
tests/
|
||||
apps/
|
||||
platform/
|
||||
website/
|
||||
docs/
|
||||
specs/
|
||||
scripts/
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
# Add commands for PHP 8.4.15
|
||||
- Root workspace:
|
||||
- `corepack pnpm install`
|
||||
- `corepack pnpm dev:platform`
|
||||
- `corepack pnpm dev:website`
|
||||
- `corepack pnpm dev`
|
||||
- `corepack pnpm build:website`
|
||||
- `corepack pnpm build:platform`
|
||||
- Platform app:
|
||||
- `cd apps/platform && ./vendor/bin/sail up -d`
|
||||
- `cd apps/platform && ./vendor/bin/sail pnpm dev`
|
||||
- `cd apps/platform && ./vendor/bin/sail pnpm build`
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact`
|
||||
|
||||
## Code Style
|
||||
|
||||
PHP 8.4.15: Follow standard conventions
|
||||
|
||||
## Recent Changes
|
||||
- 183-website-workspace-foundation: Added PHP 8.4.15 and Laravel 12 for `apps/platform`; Node.js 20+ with pnpm 10 workspace tooling; Astro v6 for `apps/website`; Bash and Docker Compose for root orchestration + `laravel/framework`, `filament/filament`, `livewire/livewire`, `laravel/sail`, `vite`, `tailwindcss`, `pnpm` workspaces, Astro, existing `./scripts/platform-sail` wrapper, repo-root Docker Compose
|
||||
- 182-platform-relocation: Added PHP 8.4.15, Laravel 12, Blade, Livewire v4, Filament v5.2.x, Tailwind CSS v4, Vite 7 + `laravel/framework`, `filament/filament`, `livewire/livewire`, `laravel/sail`, `laravel-vite-plugin`, `tailwindcss`, `vite`, `pestphp/pest`, `drizzle-kit`, PostgreSQL, Redis, Docker Compose
|
||||
- 180-tenant-backup-health: Added PHP 8.4, Laravel 12, Blade, Filament v5, Livewire v4 + Filament v5, Livewire v4, Pest v4, Laravel Sail, existing `DashboardKpis`, `NeedsAttention`, `BackupSetResource`, `BackupScheduleResource`, `BackupQualityResolver`, `BackupQualitySummary`, `ScheduleTimeService`, shared badge infrastructure, and existing RBAC helpers
|
||||
- 176-backup-quality-truth: Added PHP 8.4, Laravel 12, Blade, Filament v5, Livewire v4 + Filament v5, Livewire v4, Pest v4, Laravel Sail, existing `BackupSetResource`, `BackupItemsRelationManager`, `PolicyVersionResource`, `RestoreRunResource`, `CreateRestoreRun`, `AssignmentBackupService`, `VersionService`, `PolicySnapshotService`, `RestoreRiskChecker`, `BadgeRenderer`, `PolicySnapshotModeBadge`, `EnterpriseDetailBuilder`, and existing RBAC helpers
|
||||
<!-- MANUAL ADDITIONS START -->
|
||||
<!-- MANUAL ADDITIONS END -->
|
||||
|
||||
10
.github/copilot-instructions.md
vendored
10
.github/copilot-instructions.md
vendored
@ -291,8 +291,12 @@ ## Application Structure & Architecture
|
||||
- Stick to existing directory structure; don't create new base folders without approval.
|
||||
- Do not change the application's dependencies without approval.
|
||||
|
||||
## Workspace Commands
|
||||
- Repo-root JavaScript orchestration now uses `corepack pnpm install`, `corepack pnpm dev:platform`, `corepack pnpm dev:website`, `corepack pnpm dev`, `corepack pnpm build:website`, and `corepack pnpm build:platform`.
|
||||
- `apps/website` is a standalone Astro app, not a second Laravel runtime, so Boost MCP remains platform-only.
|
||||
|
||||
## Frontend Bundling
|
||||
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `cd apps/platform && ./vendor/bin/sail npm run build`, `cd apps/platform && ./vendor/bin/sail npm run dev`, or `cd apps/platform && ./vendor/bin/sail composer run dev`. Ask them.
|
||||
- If the user doesn't see a platform frontend change reflected in the UI, it could mean they need to run `cd apps/platform && ./vendor/bin/sail pnpm build`, `cd apps/platform && ./vendor/bin/sail pnpm dev`, or `cd apps/platform && ./vendor/bin/sail composer run dev`. Ask them.
|
||||
|
||||
## Replies
|
||||
- Be concise in your explanations - focus on what's important rather than explaining obvious details.
|
||||
@ -378,7 +382,7 @@ ## Laravel Sail
|
||||
- Always prefix PHP, Artisan, Composer, and Node commands with `cd apps/platform && ./vendor/bin/sail`. Examples:
|
||||
- Run Artisan Commands: `cd apps/platform && ./vendor/bin/sail artisan migrate`
|
||||
- Install Composer packages: `cd apps/platform && ./vendor/bin/sail composer install`
|
||||
- Execute Node commands: `cd apps/platform && ./vendor/bin/sail npm run dev`
|
||||
- Execute Node commands: `cd apps/platform && ./vendor/bin/sail pnpm dev`
|
||||
- Execute PHP scripts: `cd apps/platform && ./vendor/bin/sail php [script]`
|
||||
- View all available Sail commands by running `cd apps/platform && ./vendor/bin/sail` without arguments.
|
||||
|
||||
@ -432,7 +436,7 @@ ### Testing
|
||||
- When creating tests, make use of `cd apps/platform && ./vendor/bin/sail artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.
|
||||
|
||||
### Vite Error
|
||||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `cd apps/platform && ./vendor/bin/sail npm run build` or ask the user to run `cd apps/platform && ./vendor/bin/sail npm run dev` or `cd apps/platform && ./vendor/bin/sail composer run dev`.
|
||||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `cd apps/platform && ./vendor/bin/sail pnpm build` or ask the user to run `cd apps/platform && ./vendor/bin/sail pnpm dev` or `cd apps/platform && ./vendor/bin/sail composer run dev`.
|
||||
|
||||
=== laravel/v12 rules ===
|
||||
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@ -16,11 +16,15 @@
|
||||
/auth.json
|
||||
/node_modules
|
||||
/apps/platform/node_modules
|
||||
/apps/website/node_modules
|
||||
/.pnpm-store
|
||||
/apps/website/.astro
|
||||
dist/
|
||||
build/
|
||||
coverage/
|
||||
/public/build
|
||||
/apps/platform/public/build
|
||||
/apps/website/dist
|
||||
/public/hot
|
||||
/apps/platform/public/hot
|
||||
/public/storage
|
||||
@ -48,3 +52,5 @@ Thumbs.db
|
||||
*.swp
|
||||
/apps/platform/.env
|
||||
/apps/platform/.env.*
|
||||
/apps/website/.env
|
||||
/apps/website/.env.*
|
||||
|
||||
@ -4,6 +4,9 @@ public/build/
|
||||
apps/platform/public/build/
|
||||
node_modules/
|
||||
apps/platform/node_modules/
|
||||
apps/website/node_modules/
|
||||
apps/website/.astro/
|
||||
apps/website/dist/
|
||||
vendor/
|
||||
apps/platform/vendor/
|
||||
*.log
|
||||
|
||||
@ -11,6 +11,9 @@ coverage/
|
||||
vendor/
|
||||
apps/platform/vendor/
|
||||
apps/platform/node_modules/
|
||||
apps/website/node_modules/
|
||||
apps/website/.astro/
|
||||
apps/website/dist/
|
||||
storage/
|
||||
apps/platform/storage/
|
||||
bootstrap/cache/
|
||||
|
||||
@ -721,7 +721,9 @@ ## Application Structure & Architecture
|
||||
|
||||
## Frontend Bundling
|
||||
|
||||
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `cd apps/platform && ./vendor/bin/sail npm run build`, `cd apps/platform && ./vendor/bin/sail npm run dev`, or `cd apps/platform && ./vendor/bin/sail composer run dev`. Ask them.
|
||||
- Repo-root JavaScript orchestration now uses `corepack pnpm install`, `corepack pnpm dev:platform`, `corepack pnpm dev:website`, `corepack pnpm dev`, `corepack pnpm build:website`, and `corepack pnpm build:platform`.
|
||||
- `apps/website` is a standalone Astro app, not a second Laravel runtime, so Boost MCP remains platform-only.
|
||||
- If the user doesn't see a platform frontend change reflected in the UI, it could mean they need to run `cd apps/platform && ./vendor/bin/sail pnpm build`, `cd apps/platform && ./vendor/bin/sail pnpm dev`, or `cd apps/platform && ./vendor/bin/sail composer run dev`. Ask them.
|
||||
|
||||
## Documentation Files
|
||||
|
||||
@ -818,7 +820,7 @@ # Laravel Sail
|
||||
- Always prefix PHP, Artisan, Composer, and Node commands with `cd apps/platform && ./vendor/bin/sail`. Examples:
|
||||
- Run Artisan Commands: `cd apps/platform && ./vendor/bin/sail artisan migrate`
|
||||
- Install Composer packages: `cd apps/platform && ./vendor/bin/sail composer install`
|
||||
- Execute Node commands: `cd apps/platform && ./vendor/bin/sail npm run dev`
|
||||
- Execute Node commands: `cd apps/platform && ./vendor/bin/sail pnpm dev`
|
||||
- Execute PHP scripts: `cd apps/platform && ./vendor/bin/sail php [script]`
|
||||
- View all available Sail commands by running `cd apps/platform && ./vendor/bin/sail` without arguments.
|
||||
|
||||
@ -882,7 +884,7 @@ ## Testing
|
||||
|
||||
## Vite Error
|
||||
|
||||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `cd apps/platform && ./vendor/bin/sail npm run build` or ask the user to run `cd apps/platform && ./vendor/bin/sail npm run dev` or `cd apps/platform && ./vendor/bin/sail composer run dev`.
|
||||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `cd apps/platform && ./vendor/bin/sail pnpm build` or ask the user to run `cd apps/platform && ./vendor/bin/sail pnpm dev` or `cd apps/platform && ./vendor/bin/sail composer run dev`.
|
||||
|
||||
=== laravel/v12 rules ===
|
||||
|
||||
|
||||
@ -559,7 +559,9 @@ ## Application Structure & Architecture
|
||||
|
||||
## Frontend Bundling
|
||||
|
||||
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `cd apps/platform && ./vendor/bin/sail npm run build`, `cd apps/platform && ./vendor/bin/sail npm run dev`, or `cd apps/platform && ./vendor/bin/sail composer run dev`. Ask them.
|
||||
- Repo-root JavaScript orchestration now uses `corepack pnpm install`, `corepack pnpm dev:platform`, `corepack pnpm dev:website`, `corepack pnpm dev`, `corepack pnpm build:website`, and `corepack pnpm build:platform`.
|
||||
- `apps/website` is a standalone Astro app, not a second Laravel runtime, so Boost MCP remains platform-only.
|
||||
- If the user doesn't see a platform frontend change reflected in the UI, it could mean they need to run `cd apps/platform && ./vendor/bin/sail pnpm build`, `cd apps/platform && ./vendor/bin/sail pnpm dev`, or `cd apps/platform && ./vendor/bin/sail composer run dev`. Ask them.
|
||||
|
||||
## Documentation Files
|
||||
|
||||
@ -656,7 +658,7 @@ # Laravel Sail
|
||||
- Always prefix PHP, Artisan, Composer, and Node commands with `cd apps/platform && ./vendor/bin/sail`. Examples:
|
||||
- Run Artisan Commands: `cd apps/platform && ./vendor/bin/sail artisan migrate`
|
||||
- Install Composer packages: `cd apps/platform && ./vendor/bin/sail composer install`
|
||||
- Execute Node commands: `cd apps/platform && ./vendor/bin/sail npm run dev`
|
||||
- Execute Node commands: `cd apps/platform && ./vendor/bin/sail pnpm dev`
|
||||
- Execute PHP scripts: `cd apps/platform && ./vendor/bin/sail php [script]`
|
||||
- View all available Sail commands by running `cd apps/platform && ./vendor/bin/sail` without arguments.
|
||||
|
||||
@ -720,7 +722,7 @@ ## Testing
|
||||
|
||||
## Vite Error
|
||||
|
||||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `cd apps/platform && ./vendor/bin/sail npm run build` or ask the user to run `cd apps/platform && ./vendor/bin/sail npm run dev` or `cd apps/platform && ./vendor/bin/sail composer run dev`.
|
||||
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `cd apps/platform && ./vendor/bin/sail pnpm build` or ask the user to run `cd apps/platform && ./vendor/bin/sail pnpm dev` or `cd apps/platform && ./vendor/bin/sail composer run dev`.
|
||||
|
||||
=== laravel/v12 rules ===
|
||||
|
||||
|
||||
117
README.md
117
README.md
@ -1,26 +1,50 @@
|
||||
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
|
||||
# TenantPilot Workspace
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
|
||||
</p>
|
||||
TenantPilot is an Intune management platform built around a stable Laravel application in
|
||||
`apps/platform` and, starting with Spec 183, a standalone public Astro website in
|
||||
`apps/website`. The repository root is now the official JavaScript workspace entry point and
|
||||
orchestrates app-local commands without becoming a runtime itself.
|
||||
|
||||
## TenantPilot setup
|
||||
## Multi-App Topology
|
||||
|
||||
- `apps/platform`: the Laravel 12 + Filament v5 + Livewire v4 product runtime
|
||||
- `apps/website`: the Astro v6 public website runtime
|
||||
- repo root: workspace manifests, documentation, scripts, editor tooling, and `docker-compose.yml`
|
||||
- `./scripts/platform-sail`: platform-only compatibility helper for tooling that cannot set `cwd`
|
||||
|
||||
## Official Root Commands
|
||||
|
||||
- Install workspace-managed JavaScript dependencies: `corepack pnpm install`
|
||||
- Start the platform stack: `corepack pnpm dev:platform`
|
||||
- Start the website dev server: `corepack pnpm dev:website`
|
||||
- Start platform + website together: `corepack pnpm dev`
|
||||
- Build the website: `corepack pnpm build:website`
|
||||
- Build platform frontend assets: `corepack pnpm build:platform`
|
||||
|
||||
## App-Local Commands
|
||||
|
||||
### Platform
|
||||
|
||||
- Install PHP dependencies: `cd apps/platform && composer install`
|
||||
- Start Sail: `cd apps/platform && ./vendor/bin/sail up -d`
|
||||
- Generate the app key: `cd apps/platform && ./vendor/bin/sail artisan key:generate`
|
||||
- Run migrations and seeders: `cd apps/platform && ./vendor/bin/sail artisan migrate --seed`
|
||||
- Run frontend watch/build inside Sail: `cd apps/platform && ./vendor/bin/sail pnpm dev` or `cd apps/platform && ./vendor/bin/sail pnpm build`
|
||||
- Run tests: `cd apps/platform && ./vendor/bin/sail artisan test --compact`
|
||||
|
||||
### Website
|
||||
|
||||
- Start the dev server: `cd apps/website && pnpm dev`
|
||||
- Build the static site: `cd apps/website && pnpm build`
|
||||
|
||||
## Port Overrides
|
||||
|
||||
- Platform HTTP and Vite ports: set `APP_PORT` and or `VITE_PORT` before `corepack pnpm dev:platform` or `cd apps/platform && ./vendor/bin/sail up -d`
|
||||
- Website dev server port: set `WEBSITE_PORT` before `corepack pnpm dev:website` or pass `--port <port>` to `cd apps/website && pnpm dev`
|
||||
- Parallel local development keeps both apps isolated, even when one or both ports are overridden
|
||||
|
||||
## Platform Setup Notes
|
||||
|
||||
- Platform app root: `apps/platform`
|
||||
- Repo-root ownership: specs, docs, scripts, editor config, agent config, orchestration, and `docker-compose.yml`
|
||||
- App-root ownership: Laravel runtime, tests, Vite assets, public entrypoints, `composer.json`, `package.json`, `drizzle.config.ts`, and app-local `.env*`
|
||||
- Local dev (Sail-first, canonical workflow):
|
||||
- Install: `cd apps/platform && composer install`
|
||||
- Env bootstrap: `cd apps/platform && cp .env.example .env`
|
||||
- Start stack: `cd apps/platform && ./vendor/bin/sail up -d`
|
||||
- Generate app key: `cd apps/platform && ./vendor/bin/sail artisan key:generate`
|
||||
- Init DB: `cd apps/platform && ./vendor/bin/sail artisan migrate --seed`
|
||||
- Tests: `cd apps/platform && ./vendor/bin/sail artisan test --compact`
|
||||
- Policy sync: `cd apps/platform && ./vendor/bin/sail artisan intune:sync-policies`
|
||||
- Compatibility helper for tooling that cannot set a nested working directory: `./scripts/platform-sail ...`
|
||||
- Filament admin: `/admin` (seed user `test@example.com`, set password via factory or `artisan tinker`).
|
||||
- Microsoft Graph (Intune) env vars:
|
||||
- `GRAPH_TENANT_ID`
|
||||
@ -41,7 +65,7 @@ ## Platform relocation rollout notes
|
||||
|
||||
- Open branches that still touch legacy root app paths should merge `dev` first, then remap file moves from `app/`, `bootstrap/`, `config/`, `database/`, `lang/`, `public/`, `resources/`, `routes/`, `storage/`, and `tests/` into `apps/platform/...`.
|
||||
- Keep using merge-based catch-up on shared feature branches; do not rebase long-lived shared branches just to absorb the relocation.
|
||||
- VS Code tasks and MCP launchers now delegate through `./scripts/platform-sail` from the repo root. Human-facing docs remain `apps/platform`-first.
|
||||
- VS Code tasks expose the official root workspace commands, while MCP launchers remain platform-only and delegate through `./scripts/platform-sail`.
|
||||
|
||||
## Bulk operations (Feature 005)
|
||||
|
||||
@ -118,54 +142,3 @@ ## Policy JSON Viewer (Feature 002)
|
||||
- Scrollable container with max height to prevent page overflow
|
||||
- **Usage**: See `specs/002-filament-json/quickstart.md` for detailed examples and configuration
|
||||
- **Performance**: Optimized for payloads up to 1 MB; auto-collapse improves initial render for large snapshots
|
||||
|
||||
## About Laravel
|
||||
|
||||
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
||||
|
||||
- [Simple, fast routing engine](https://laravel.com/docs/routing).
|
||||
- [Powerful dependency injection container](https://laravel.com/docs/container).
|
||||
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
|
||||
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
|
||||
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
|
||||
- [Robust background job processing](https://laravel.com/docs/queues).
|
||||
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
|
||||
|
||||
Laravel is accessible, powerful, and provides tools required for large, robust applications.
|
||||
|
||||
## Learning Laravel
|
||||
|
||||
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. You can also check out [Laravel Learn](https://laravel.com/learn), where you will be guided through building a modern Laravel application.
|
||||
|
||||
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
|
||||
|
||||
## Laravel Sponsors
|
||||
|
||||
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com).
|
||||
|
||||
### Premium Partners
|
||||
|
||||
- **[Vehikl](https://vehikl.com)**
|
||||
- **[Tighten Co.](https://tighten.co)**
|
||||
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
|
||||
- **[64 Robots](https://64robots.com)**
|
||||
- **[Curotec](https://www.curotec.com/services/technologies/laravel)**
|
||||
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
|
||||
- **[Redberry](https://redberry.international/laravel-development)**
|
||||
- **[Active Logic](https://activelogic.com)**
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
|
||||
|
||||
## License
|
||||
|
||||
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
|
||||
@ -45,12 +45,12 @@
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"",
|
||||
"@php artisan key:generate",
|
||||
"@php artisan migrate --force",
|
||||
"npm install",
|
||||
"npm run build"
|
||||
"pnpm install",
|
||||
"pnpm build"
|
||||
],
|
||||
"dev": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
|
||||
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"pnpm dev\" --names=server,queue,logs,vite --kill-others"
|
||||
],
|
||||
"test": [
|
||||
"@php artisan config:clear --ansi",
|
||||
|
||||
3745
apps/platform/package-lock.json
generated
3745
apps/platform/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,13 @@
|
||||
{
|
||||
"$schema": "https://www.schemastore.org/package.json",
|
||||
"name": "@tenantatlas/platform",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"dev": "vite",
|
||||
"sail:build": "./vendor/bin/sail npm run build",
|
||||
"sail:dev": "./vendor/bin/sail npm run dev"
|
||||
"sail:build": "./vendor/bin/sail pnpm build",
|
||||
"sail:dev": "./vendor/bin/sail pnpm dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use App\Providers\Filament\AdminPanelProvider;
|
||||
use App\Providers\Filament\SystemPanelProvider;
|
||||
use App\Providers\Filament\TenantPanelProvider;
|
||||
|
||||
it('keeps the platform health and admin login routes reachable', function () {
|
||||
$this->get('/up')->assertSuccessful();
|
||||
$this->get('/admin/login')->assertSuccessful();
|
||||
});
|
||||
|
||||
it('keeps panel providers registered from apps/platform/bootstrap/providers.php', function () {
|
||||
$providers = require base_path('bootstrap/providers.php');
|
||||
|
||||
expect($providers)
|
||||
->toContain(AdminPanelProvider::class)
|
||||
->toContain(TenantPanelProvider::class)
|
||||
->toContain(SystemPanelProvider::class);
|
||||
});
|
||||
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
function decodeJsonFile(string $path): array
|
||||
{
|
||||
$decoded = json_decode(file_get_contents($path), true);
|
||||
|
||||
expect($decoded)->toBeArray();
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
it('defines the official root workspace command model', function () {
|
||||
$package = decodeJsonFile(repo_path('package.json'));
|
||||
|
||||
expect($package['packageManager'] ?? null)->toBe('pnpm@10.33.0');
|
||||
expect($package['scripts'] ?? [])
|
||||
->toHaveKeys([
|
||||
'dev',
|
||||
'dev:platform',
|
||||
'dev:website',
|
||||
'build:platform',
|
||||
'build:website',
|
||||
]);
|
||||
expect($package['scripts']['dev'] ?? null)->toContain('corepack pnpm dev:website');
|
||||
expect($package['scripts']['dev:platform'] ?? null)->toBe('./scripts/platform-sail up -d');
|
||||
expect($package['scripts']['dev:website'] ?? null)->toContain('WEBSITE_PORT=${WEBSITE_PORT:-4321}');
|
||||
expect($package['scripts']['build:platform'] ?? null)->toContain('@tenantatlas/platform build');
|
||||
expect($package['scripts']['build:website'] ?? null)->toContain('@tenantatlas/website build');
|
||||
});
|
||||
|
||||
it('binds the repo to apps workspaces and removes the legacy npm lockfile', function () {
|
||||
$workspaceDefinition = file_get_contents(repo_path('pnpm-workspace.yaml'));
|
||||
|
||||
expect($workspaceDefinition)->toContain('apps/*');
|
||||
expect(file_exists(repo_path('apps/platform/package-lock.json')))->toBeFalse();
|
||||
});
|
||||
|
||||
it('keeps platform and website manifests aligned to the workspace boundary', function () {
|
||||
$platformPackage = decodeJsonFile(repo_path('apps/platform/package.json'));
|
||||
$websitePackage = decodeJsonFile(repo_path('apps/website/package.json'));
|
||||
|
||||
expect($platformPackage['name'] ?? null)->toBe('@tenantatlas/platform');
|
||||
expect($platformPackage['scripts']['sail:dev'] ?? null)->toBe('./vendor/bin/sail pnpm dev');
|
||||
expect($platformPackage['scripts']['sail:build'] ?? null)->toBe('./vendor/bin/sail pnpm build');
|
||||
|
||||
expect($websitePackage['name'] ?? null)->toBe('@tenantatlas/website');
|
||||
expect($websitePackage['scripts'] ?? [])
|
||||
->toHaveKeys(['dev', 'build', 'preview']);
|
||||
expect($websitePackage['scripts']['dev'] ?? null)->toContain('${WEBSITE_PORT:-4321}');
|
||||
});
|
||||
9
apps/website/astro.config.mjs
Normal file
9
apps/website/astro.config.mjs
Normal file
@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
export default defineConfig({
|
||||
output: 'static',
|
||||
server: {
|
||||
host: true,
|
||||
port: 4321,
|
||||
},
|
||||
});
|
||||
17
apps/website/package.json
Normal file
17
apps/website/package.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@tenantatlas/website",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "astro dev --host 0.0.0.0 --port ${WEBSITE_PORT:-4321}",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview --host 0.0.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^6.0.0"
|
||||
}
|
||||
}
|
||||
11
apps/website/public/favicon.svg
Normal file
11
apps/website/public/favicon.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
||||
<rect width="64" height="64" rx="18" fill="#17120F" />
|
||||
<path
|
||||
d="M17 18H47V25H36V46H28V25H17V18Z"
|
||||
fill="#FFF7F1"
|
||||
/>
|
||||
<path
|
||||
d="M44 17C50.0751 17 55 21.9249 55 28C55 34.0751 50.0751 39 44 39H39V32H44C46.2091 32 48 30.2091 48 28C48 25.7909 46.2091 24 44 24H39V17H44Z"
|
||||
fill="#CC5F2C"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 413 B |
2
apps/website/public/robots.txt
Normal file
2
apps/website/public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
27
apps/website/src/layouts/BaseLayout.astro
Normal file
27
apps/website/src/layouts/BaseLayout.astro
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
import '../styles/global.css';
|
||||
|
||||
interface Props {
|
||||
description?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
description = 'TenantPilot keeps Intune governance observable, reviewable, and safe to operate.',
|
||||
title = 'TenantPilot',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content={description} />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
66
apps/website/src/pages/index.astro
Normal file
66
apps/website/src/pages/index.astro
Normal file
@ -0,0 +1,66 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="TenantPilot | Workspace Foundation"
|
||||
description="The first public TenantPilot website surface for workspace-safe Intune operations."
|
||||
>
|
||||
<main class="page-shell">
|
||||
<section class="hero">
|
||||
<p class="eyebrow">TenantPilot</p>
|
||||
<h1>One public website, one stable platform, one clear workspace model.</h1>
|
||||
<p class="lede">
|
||||
TenantPilot keeps Intune change management auditable for operators while the public
|
||||
website stays fast, static, and operationally separate from the Laravel platform.
|
||||
</p>
|
||||
|
||||
<div class="hero-actions">
|
||||
<a class="primary-action" href="#workspace-model">View the workspace model</a>
|
||||
<a class="secondary-action" href="#boundaries">Review the isolation rules</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="signal-grid" id="workspace-model" aria-label="Workspace foundations">
|
||||
<article class="signal-card">
|
||||
<p class="signal-label">Platform</p>
|
||||
<h2>Laravel stays in <code>apps/platform</code>.</h2>
|
||||
<p>
|
||||
Sail, Filament, Livewire, and deployment-sensitive runtime concerns remain
|
||||
platform-owned and unchanged.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="signal-card">
|
||||
<p class="signal-label">Website</p>
|
||||
<h2>Astro lives independently in <code>apps/website</code>.</h2>
|
||||
<p>
|
||||
Public pages build statically, run without Laravel, and keep their own dev and
|
||||
build outputs.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="signal-card">
|
||||
<p class="signal-label">Root</p>
|
||||
<h2>The repository root orchestrates without becoming an app.</h2>
|
||||
<p>
|
||||
Root scripts expose the official entry commands while app-local execution logic
|
||||
stays inside each app directory.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="boundary-panel" id="boundaries">
|
||||
<div>
|
||||
<p class="eyebrow">Isolation</p>
|
||||
<h2>Builds, ports, and ownership stay intentionally separate.</h2>
|
||||
</div>
|
||||
|
||||
<ul class="boundary-list">
|
||||
<li>Website dev defaults to port 4321 and supports explicit port overrides.</li>
|
||||
<li>Platform Docker, queues, and Filament assets stay under the existing Sail flow.</li>
|
||||
<li>No shared package layer, CMS, or extra app surface is introduced in this slice.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
</BaseLayout>
|
||||
221
apps/website/src/styles/global.css
Normal file
221
apps/website/src/styles/global.css
Normal file
@ -0,0 +1,221 @@
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--bg: #f6efe5;
|
||||
--bg-accent: #fffdf9;
|
||||
--surface: rgba(255, 255, 255, 0.74);
|
||||
--surface-strong: rgba(255, 255, 255, 0.92);
|
||||
--ink: #17120f;
|
||||
--muted: #66584d;
|
||||
--line: rgba(23, 18, 15, 0.12);
|
||||
--accent: #cc5f2c;
|
||||
--accent-deep: #8b3820;
|
||||
--shadow: 0 30px 80px rgba(103, 52, 33, 0.16);
|
||||
font-family: "Avenir Next", "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(255, 201, 149, 0.55), transparent 34%),
|
||||
radial-gradient(circle at right 12% top 10%, rgba(255, 145, 96, 0.18), transparent 24%),
|
||||
linear-gradient(180deg, #fffaf3 0%, var(--bg) 58%, #efe3d5 100%);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "SFMono-Regular", "SF Mono", "IBM Plex Mono", monospace;
|
||||
font-size: 0.92em;
|
||||
}
|
||||
|
||||
.page-shell {
|
||||
width: min(1120px, calc(100% - 2rem));
|
||||
margin: 0 auto;
|
||||
padding: 4.5rem 0 5rem;
|
||||
}
|
||||
|
||||
.hero,
|
||||
.signal-card,
|
||||
.boundary-panel {
|
||||
backdrop-filter: blur(18px);
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.hero {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: clamp(2rem, 4vw, 4.5rem);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 2rem;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(255, 255, 255, 0.88), rgba(255, 247, 239, 0.72)),
|
||||
linear-gradient(120deg, rgba(204, 95, 44, 0.08), rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: auto -8rem -8rem auto;
|
||||
width: 18rem;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 999px;
|
||||
background: radial-gradient(circle, rgba(204, 95, 44, 0.22), transparent 72%);
|
||||
}
|
||||
|
||||
.eyebrow,
|
||||
.signal-label {
|
||||
margin: 0 0 0.9rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.18em;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent-deep);
|
||||
}
|
||||
|
||||
.hero h1,
|
||||
.boundary-panel h2,
|
||||
.signal-card h2 {
|
||||
margin: 0;
|
||||
font-family: "Iowan Old Style", "Palatino Linotype", serif;
|
||||
line-height: 0.95;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
max-width: 13ch;
|
||||
font-size: clamp(3rem, 8vw, 6rem);
|
||||
}
|
||||
|
||||
.lede {
|
||||
max-width: 46rem;
|
||||
margin: 1.5rem 0 0;
|
||||
font-size: clamp(1.05rem, 2vw, 1.35rem);
|
||||
line-height: 1.7;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.primary-action,
|
||||
.secondary-action {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 3.25rem;
|
||||
padding: 0.9rem 1.4rem;
|
||||
border-radius: 999px;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
transition:
|
||||
transform 180ms ease,
|
||||
box-shadow 180ms ease,
|
||||
background-color 180ms ease;
|
||||
}
|
||||
|
||||
.primary-action {
|
||||
background: var(--ink);
|
||||
color: #fff7f1;
|
||||
}
|
||||
|
||||
.secondary-action {
|
||||
border: 1px solid rgba(23, 18, 15, 0.12);
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.primary-action:hover,
|
||||
.secondary-action:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.signal-grid {
|
||||
display: grid;
|
||||
gap: 1.25rem;
|
||||
margin-top: 1.4rem;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.signal-card,
|
||||
.boundary-panel {
|
||||
padding: 1.6rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 1.5rem;
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
.signal-card h2 {
|
||||
font-size: clamp(1.55rem, 3vw, 2.1rem);
|
||||
}
|
||||
|
||||
.signal-card p:last-child,
|
||||
.boundary-list {
|
||||
margin: 1rem 0 0;
|
||||
color: var(--muted);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.boundary-panel {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
margin-top: 1.25rem;
|
||||
background: var(--surface-strong);
|
||||
}
|
||||
|
||||
.boundary-panel h2 {
|
||||
font-size: clamp(2rem, 4vw, 3.1rem);
|
||||
}
|
||||
|
||||
.boundary-list {
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
.boundary-list li + li {
|
||||
margin-top: 0.7rem;
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
.signal-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.page-shell {
|
||||
width: min(100% - 1.25rem, 1120px);
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
.hero,
|
||||
.signal-card,
|
||||
.boundary-panel {
|
||||
border-radius: 1.3rem;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 1.4rem;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.primary-action,
|
||||
.secondary-action {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@ # TenantPilot / TenantAtlas — Handover Document
|
||||
## Executive Summary
|
||||
|
||||
- **Platform relocation addendum (Spec 182)**: The Laravel application now lives under `apps/platform`; repo root remains the orchestration and metadata layer.
|
||||
- **Canonical command model**: Human-facing app commands now start from `apps/platform`; repo-root launcher files such as VS Code MCP and task integrations delegate via `./scripts/platform-sail`.
|
||||
- **Canonical command model**: Human-facing platform commands still start from `apps/platform`, while repo-root pnpm commands now orchestrate `apps/platform` and `apps/website` for multi-app local development.
|
||||
- **Branch-impact warning**: Open branches that still modify legacy root app paths should merge `dev` and remap their changes into `apps/platform/...` before continuing.
|
||||
- **Rollout unknowns**: Dokploy build context, web/queue/scheduler working directories, and volume mappings for `public/` and `storage/` still require staging verification after the relocation.
|
||||
|
||||
@ -427,20 +427,26 @@ ## Deployment & Runbooks
|
||||
### Local development
|
||||
|
||||
```bash
|
||||
# Start services
|
||||
vendor/bin/sail up -d
|
||||
# Start platform services
|
||||
cd apps/platform && ./vendor/bin/sail up -d
|
||||
|
||||
# Run migrations
|
||||
vendor/bin/sail artisan migrate
|
||||
cd apps/platform && ./vendor/bin/sail artisan migrate
|
||||
|
||||
# Start queue worker (or use docker-compose queue service)
|
||||
vendor/bin/sail artisan queue:work --tries=3 --timeout=300
|
||||
cd apps/platform && ./vendor/bin/sail artisan queue:work --tries=3 --timeout=300
|
||||
|
||||
# Build frontend assets
|
||||
vendor/bin/sail npm run build
|
||||
cd apps/platform && ./vendor/bin/sail pnpm build
|
||||
|
||||
# Install workspace JavaScript dependencies
|
||||
corepack pnpm install
|
||||
|
||||
# Start the website
|
||||
corepack pnpm dev:website
|
||||
|
||||
# Run tests
|
||||
vendor/bin/sail artisan test --compact
|
||||
cd apps/platform && ./vendor/bin/sail artisan test --compact
|
||||
```
|
||||
|
||||
### Docker services ([docker-compose.yml](docker-compose.yml))
|
||||
@ -493,7 +499,7 @@ ## Next Actions (Top 5)
|
||||
|
||||
1. **Create `.env.example`** — Document all required env vars from `config/*.php` files. Low effort, high impact for onboarding.
|
||||
|
||||
2. **Add CI pipeline** — Gitea / runner config for `vendor/bin/sail artisan test --compact` + `vendor/bin/sail bin pint --test` on every PR. Critical for sustained quality.
|
||||
2. **Add CI pipeline** — Gitea / runner config for `cd apps/platform && ./vendor/bin/sail artisan test --compact` + `cd apps/platform && ./vendor/bin/sail bin pint --test` on every PR. Critical for sustained quality.
|
||||
|
||||
3. **Formal exception/risk-acceptance spec** — Design `FindingException` entity with approval chain, evidence attachment, and UI workflow. Blocks R2 "Evidence Packs" roadmap item.
|
||||
|
||||
@ -628,33 +634,35 @@ ### Key Commands
|
||||
|
||||
```bash
|
||||
# Local dev
|
||||
vendor/bin/sail up -d # Start all services
|
||||
vendor/bin/sail artisan migrate # Run migrations
|
||||
vendor/bin/sail artisan queue:work --tries=3 # Process queue
|
||||
vendor/bin/sail npm run build # Build frontend
|
||||
corepack pnpm install # Install workspace JS dependencies
|
||||
corepack pnpm dev:platform # Start the platform stack
|
||||
corepack pnpm dev:website # Start the website
|
||||
corepack pnpm build:website # Build the website
|
||||
cd apps/platform && ./vendor/bin/sail pnpm build # Build platform frontend
|
||||
|
||||
# Testing
|
||||
vendor/bin/sail artisan test --compact # Full suite
|
||||
vendor/bin/sail artisan test --compact --filter=testName # Single test
|
||||
vendor/bin/sail artisan test --compact tests/Feature/Guards/ # Guard tests only
|
||||
cd apps/platform && ./vendor/bin/sail artisan test --compact # Full suite
|
||||
cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=testName # Single test
|
||||
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/ # Guard tests only
|
||||
|
||||
# Code quality
|
||||
vendor/bin/sail bin pint --dirty # Format changed files
|
||||
cd apps/platform && ./vendor/bin/sail bin pint --dirty # Format changed files
|
||||
|
||||
# Deployment
|
||||
vendor/bin/sail artisan filament:assets # Publish Filament assets
|
||||
vendor/bin/sail artisan migrate --force # Production migration
|
||||
cd apps/platform && php artisan filament:assets # Publish Filament assets
|
||||
cd apps/platform && php artisan migrate --force # Production migration
|
||||
```
|
||||
|
||||
### Quickstart (exact steps)
|
||||
|
||||
1. Clone repo, `cd TenantAtlas`
|
||||
2. `cp .env.example .env` (MISSING — create from config files or request from team)
|
||||
3. `composer install`
|
||||
4. `vendor/bin/sail up -d`
|
||||
5. `vendor/bin/sail artisan key:generate`
|
||||
6. `vendor/bin/sail artisan migrate`
|
||||
7. `vendor/bin/sail npm install && vendor/bin/sail npm run build`
|
||||
8. `vendor/bin/sail artisan filament:assets`
|
||||
9. Login: Navigate to `/admin` — redirects to workspace chooser. For first-time setup, create a workspace and onboard a tenant via the wizard.
|
||||
10. System console: Navigate to `/system` — requires `platform_users` record with `platform` guard.
|
||||
3. `corepack pnpm install`
|
||||
4. `cd apps/platform && composer install`
|
||||
5. `cd apps/platform && ./vendor/bin/sail up -d`
|
||||
6. `cd apps/platform && ./vendor/bin/sail artisan key:generate`
|
||||
7. `cd apps/platform && ./vendor/bin/sail artisan migrate`
|
||||
8. `cd apps/platform && ./vendor/bin/sail pnpm build`
|
||||
9. `cd apps/platform && php artisan filament:assets`
|
||||
10. Login: Navigate to `/admin` — redirects to workspace chooser. For first-time setup, create a workspace and onboard a tenant via the wizard.
|
||||
11. System console: Navigate to `/system` — requires `platform_users` record with `platform` guard.
|
||||
|
||||
@ -5,21 +5,27 @@
|
||||
**Overview:**
|
||||
- **Purpose:** Intune management tool (backup, restore, policy versioning, safe change management) built with Laravel + Filament.
|
||||
- **Primary goals:** policy version control (diff/history/rollback), reliable backup & restore of Microsoft Intune configuration, admin-focused productivity features, auditability and least-privilege operations.
|
||||
- **Workspace model:** repo-root pnpm workspace orchestration, Laravel platform in `apps/platform`, and standalone Astro website in `apps/website`.
|
||||
|
||||
**Tech Stack & Key Libraries:**
|
||||
- **Backend:** Laravel 12 (PHP 8.4)
|
||||
- **Admin UI:** Filament v4
|
||||
- **Realtime/UI:** Livewire v3
|
||||
- **Admin UI:** Filament v5
|
||||
- **Realtime/UI:** Livewire v4
|
||||
- **Public website:** Astro v6
|
||||
- **Workspace tooling:** pnpm 10 workspaces
|
||||
- **Testing:** Pest v4, PHPUnit
|
||||
- **Local dev:** Laravel Sail (Docker)
|
||||
- **Styling/tooling:** Tailwind v4, Vite
|
||||
|
||||
**Repository Layout (high level):**
|
||||
- `app/` — application code (Services, Models, Filament resources, Livewire components)
|
||||
- `config/` — runtime configuration (important: `tenantpilot.php`, `graph_contracts.php`)
|
||||
- `apps/platform/` — Laravel runtime, Filament panels, tests, Vite assets, and app-local PHP or Node manifests
|
||||
- `apps/website/` — Astro website source, public assets, and static build output
|
||||
- `package.json` + `pnpm-workspace.yaml` — official root workspace command model
|
||||
- `scripts/` — root compatibility helpers such as `platform-sail`
|
||||
- `specs/` — SpecKit feature specs (feature-by-feature directories, e.g. `011-restore-run-wizard`)
|
||||
- `docs/` — architecture, rollout, and handover notes
|
||||
- `tests/` — Pest tests (Feature / Unit)
|
||||
- `resources/`, `routes/`, `database/` — standard Laravel layout
|
||||
- `apps/platform/resources/`, `apps/platform/routes/`, `apps/platform/database/` — Laravel application structure
|
||||
|
||||
**Core Features (implemented / status):**
|
||||
- **Policy Backup & Versioning:** implemented — captures immutable snapshots (JSONB), tracks metadata (tenant, type, created_by, timestamps). (See `app/Services/Intune/*`, `database/migrations`.)
|
||||
@ -54,10 +60,11 @@
|
||||
- Added `Agents.md` section for a “Solo + Copilot Workflow” and created a small `chore/solo-copilot-workflow` branch/PR for that documentation change.
|
||||
|
||||
**Where to look first (entry points):**
|
||||
- Restore flows: `app/Services/Intune/RestoreService.php`, `app/Services/Intune/RestoreRiskChecker.php`, `app/Services/Intune/RestoreDiffGenerator.php`.
|
||||
- Graph contracts: `config/graph_contracts.php` and `app/Services/Graph/GraphContractRegistry.php`.
|
||||
- Policy type catalog and UX metadata: `config/tenantpilot.php` and `specs/*` for feature intentions.
|
||||
- Filament UI: `app/Filament/Resources/*` (PolicyVersionResource, restore wizard pages).
|
||||
- Root workspace entry: `package.json`, `pnpm-workspace.yaml`, and `README.md`
|
||||
- Restore flows: `apps/platform/app/Services/Intune/RestoreService.php`, `apps/platform/app/Services/Intune/RestoreRiskChecker.php`, `apps/platform/app/Services/Intune/RestoreDiffGenerator.php`
|
||||
- Graph contracts: `apps/platform/config/graph_contracts.php` and `apps/platform/app/Services/Graph/GraphContractRegistry.php`
|
||||
- Policy type catalog and UX metadata: `apps/platform/config/tenantpilot.php` and `specs/*` for feature intentions
|
||||
- Filament UI: `apps/platform/app/Filament/Resources/*` (PolicyVersionResource, restore wizard pages)
|
||||
|
||||
**Short list of known limitations / next work items:**
|
||||
- Convert more `preview-only` types to `enabled` where safe (requires implementation of restore flows and risk mitigation, e.g., Conditional Access, Enrollment subtypes, Security Baselines).
|
||||
|
||||
15
package.json
Normal file
15
package.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "tenantatlas-workspace",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "./scripts/platform-sail up -d && corepack pnpm dev:website",
|
||||
"dev:platform": "./scripts/platform-sail up -d",
|
||||
"dev:website": "WEBSITE_PORT=${WEBSITE_PORT:-4321} corepack pnpm --filter @tenantatlas/website dev",
|
||||
"build:platform": "corepack pnpm --filter @tenantatlas/platform build",
|
||||
"build:website": "corepack pnpm --filter @tenantatlas/website build"
|
||||
}
|
||||
}
|
||||
4572
pnpm-lock.yaml
Normal file
4572
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- apps/*
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Platform-only compatibility wrapper for repo-root tooling.
|
||||
# Official root workspace scripts may orchestrate through this helper, but the
|
||||
# authoritative Sail runtime still lives under apps/platform.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
APP_DIR="${SCRIPT_DIR}/../apps/platform"
|
||||
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
# Specification Quality Checklist: Website / Workspace Foundation
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2026-04-08
|
||||
**Feature**: [spec.md](../spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined
|
||||
- [x] Edge cases are identified
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria
|
||||
- [x] User scenarios cover primary flows
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- Validation completed on 2026-04-08.
|
||||
- The spec intentionally stays at the feature-contract level: it defines one official workspace standard, one standalone website app, and strict app-boundary rules without prescribing low-level implementation structure.
|
||||
@ -0,0 +1,72 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Website + Platform Coexistence Smoke Contract
|
||||
version: 1.0.0
|
||||
summary: Minimal smoke contract for the first multi-app TenantAtlas workspace
|
||||
servers:
|
||||
- url: http://localhost
|
||||
description: Platform app via Sail on the default host port
|
||||
- url: http://localhost:{platform_port}
|
||||
description: Platform app via Sail when APP_PORT overrides the default host port
|
||||
variables:
|
||||
platform_port:
|
||||
default: '8080'
|
||||
description: Non-default APP_PORT value used during smoke validation
|
||||
- url: http://localhost:4321
|
||||
description: Website app via Astro dev server on the default port
|
||||
- url: http://localhost:{website_port}
|
||||
description: Website app via Astro dev server when WEBSITE_PORT or --port overrides the default port
|
||||
variables:
|
||||
website_port:
|
||||
default: '4322'
|
||||
description: Non-default website port used during smoke validation
|
||||
paths:
|
||||
/up:
|
||||
get:
|
||||
summary: Platform health endpoint responds successfully
|
||||
operationId: platformHealth
|
||||
servers:
|
||||
- url: http://localhost
|
||||
description: Platform app via Sail on the default host port
|
||||
- url: http://localhost:{platform_port}
|
||||
description: Platform app via Sail when APP_PORT overrides the default host port
|
||||
variables:
|
||||
platform_port:
|
||||
default: '8080'
|
||||
description: Non-default APP_PORT value used during smoke validation
|
||||
responses:
|
||||
'200':
|
||||
description: Platform boot is healthy
|
||||
/admin/login:
|
||||
get:
|
||||
summary: Platform admin login shell remains reachable
|
||||
operationId: platformAdminLogin
|
||||
servers:
|
||||
- url: http://localhost
|
||||
description: Platform app via Sail on the default host port
|
||||
- url: http://localhost:{platform_port}
|
||||
description: Platform app via Sail when APP_PORT overrides the default host port
|
||||
variables:
|
||||
platform_port:
|
||||
default: '8080'
|
||||
description: Non-default APP_PORT value used during smoke validation
|
||||
responses:
|
||||
'200':
|
||||
description: Platform admin login page renders
|
||||
/:
|
||||
get:
|
||||
summary: Website home page renders independently
|
||||
operationId: websiteHome
|
||||
servers:
|
||||
- url: http://localhost:4321
|
||||
description: Website app via Astro dev server on the default port
|
||||
- url: http://localhost:{website_port}
|
||||
description: Website app via Astro dev server when WEBSITE_PORT or --port overrides the default port
|
||||
variables:
|
||||
website_port:
|
||||
default: '4322'
|
||||
description: Non-default website port used during smoke validation
|
||||
responses:
|
||||
'200':
|
||||
description: Website home page renders on its own dev server
|
||||
components: {}
|
||||
@ -0,0 +1,70 @@
|
||||
# Contract: Workspace Command Model
|
||||
|
||||
## Purpose
|
||||
|
||||
Define the official repo-root and app-local commands for the first multi-app TenantAtlas workspace.
|
||||
|
||||
## Ownership Rule
|
||||
|
||||
- Root commands orchestrate.
|
||||
- App-local commands execute.
|
||||
- The root must never re-implement platform or website runtime logic.
|
||||
|
||||
## Official Root Commands
|
||||
|
||||
| Command | Responsibility | Notes |
|
||||
|---------|----------------|-------|
|
||||
| `pnpm install` | Install workspace JavaScript dependencies | Root entry for workspace-managed JS dependencies |
|
||||
| `pnpm dev:platform` | Start the platform app | Delegates to the existing platform Sail flow |
|
||||
| `pnpm dev:website` | Start the website app | Runs the Astro dev server from `apps/website` |
|
||||
| `pnpm dev` | Start platform + website for parallel local development | Platform may background via Sail while website dev stays foreground |
|
||||
| `pnpm build:website` | Build the website app | Produces website-only artifacts |
|
||||
| `pnpm build:platform` | Build platform frontend assets | Delegates into `apps/platform` and preserves existing Laravel asset flow |
|
||||
|
||||
## Supported Port Override Path
|
||||
|
||||
- If the platform HTTP or Vite ports are already in use, the supported override path is environment-based: set `APP_PORT` and or `VITE_PORT` before invoking the root platform command, and pass the same variables through the app-local Sail flow when using `apps/platform` directly.
|
||||
- If the website port is already in use, the supported override path is environment-based: set `WEBSITE_PORT` before invoking the root website or parallel-dev command, and pass the equivalent `--port` flag through the app-local `apps/website` Astro dev command.
|
||||
- The root `pnpm dev:website` and `pnpm dev` scripts must forward `WEBSITE_PORT` to the Astro dev server.
|
||||
- The supported override path must be documented in the root README and validated in smoke checks.
|
||||
|
||||
## Valid App-local Commands
|
||||
|
||||
### Platform
|
||||
|
||||
- `cd apps/platform && ./vendor/bin/sail up -d`
|
||||
- `cd apps/platform && ./vendor/bin/sail stop`
|
||||
- `cd apps/platform && ./vendor/bin/sail pnpm dev`
|
||||
- `cd apps/platform && ./vendor/bin/sail pnpm build`
|
||||
- `cd apps/platform && ./vendor/bin/sail artisan test --compact`
|
||||
|
||||
### Website
|
||||
|
||||
- `cd apps/website && pnpm dev`
|
||||
- `cd apps/website && pnpm build`
|
||||
|
||||
## Compatibility Helpers
|
||||
|
||||
- `./scripts/platform-sail ...` remains valid for tooling that cannot set `cwd`.
|
||||
- This helper is platform-specific in this slice and must not be generalized into a multi-app runner yet.
|
||||
|
||||
## Tooling Scope Rules
|
||||
|
||||
- `.vscode/mcp.json` and `opencode.json` remain platform-only because Boost MCP is Laravel-specific.
|
||||
- VS Code tasks may expose official root entry tasks for platform, website, and parallel dev, but must not imply a second hidden workflow.
|
||||
|
||||
## Invariants
|
||||
|
||||
- The platform remains Sail-first.
|
||||
- The website remains independent of Sail, Laravel, Blade, Filament, and platform sessions.
|
||||
- Composer remains app-local PHP dependency management for `apps/platform`.
|
||||
- pnpm is the one official JavaScript workspace/package-manager standard.
|
||||
- No root command may require the website build to start the platform or vice versa.
|
||||
|
||||
## Failure Conditions
|
||||
|
||||
- A root command is undocumented but treated as official.
|
||||
- A website command depends on platform runtime state.
|
||||
- A platform command requires undocumented root-only state.
|
||||
- Root tooling suggests npm for one app and pnpm for another as equal official workflows.
|
||||
- Port conflicts exist but no documented, supported override path is available for the platform or website commands.
|
||||
154
specs/183-website-workspace-foundation/data-model.md
Normal file
154
specs/183-website-workspace-foundation/data-model.md
Normal file
@ -0,0 +1,154 @@
|
||||
# Data Model: Website / Workspace Foundation
|
||||
|
||||
This feature does not introduce database entities. The relevant model is the set of repository-owned artifacts and runtime boundaries that define how the multi-app workspace behaves.
|
||||
|
||||
## 1. RootWorkspace
|
||||
|
||||
**Purpose**: The canonical repo-level contract for JavaScript workspace orchestration and contributor entry paths.
|
||||
|
||||
**Backed by**:
|
||||
- Root `package.json`
|
||||
- Root `pnpm-workspace.yaml`
|
||||
- Root lockfile (`pnpm-lock.yaml`)
|
||||
- Root README and root tooling guidance
|
||||
|
||||
**Key fields / responsibilities**:
|
||||
- Official package-manager declaration
|
||||
- Workspace package globs (`apps/*`)
|
||||
- Official root scripts for platform start, website start, parallel dev, website build, and platform frontend build
|
||||
- Documentation of the root-versus-app ownership model
|
||||
|
||||
**Validation rules**:
|
||||
- Must include `apps/platform` and `apps/website` as workspace applications
|
||||
- Must not claim ownership of app-local runtime logic
|
||||
- Must not introduce `packages/` or additional app surfaces in this slice
|
||||
|
||||
## 2. PlatformApp
|
||||
|
||||
**Purpose**: The existing TenantPilot Laravel runtime under `apps/platform`.
|
||||
|
||||
**Backed by**:
|
||||
- `apps/platform/composer.json`
|
||||
- `apps/platform/package.json`
|
||||
- `apps/platform/artisan`
|
||||
- `apps/platform/bootstrap/`
|
||||
- `apps/platform/public/`
|
||||
- `apps/platform/resources/`
|
||||
- `apps/platform/tests/`
|
||||
- Existing Sail/Compose integration via `./scripts/platform-sail`
|
||||
|
||||
**Key fields / responsibilities**:
|
||||
- Laravel application runtime and PHP dependency management
|
||||
- Filament admin/system/tenant panels
|
||||
- Platform frontend assets and Vite configuration
|
||||
- Platform test surface and deployment-time asset publishing
|
||||
|
||||
**Validation rules**:
|
||||
- Must remain functional under the new root workspace model
|
||||
- Must stay on Filament v5 with Livewire v4
|
||||
- Provider registration remains in `apps/platform/bootstrap/providers.php`
|
||||
- Platform assets remain isolated under platform-owned paths
|
||||
|
||||
## 3. WebsiteApp
|
||||
|
||||
**Purpose**: The new standalone public website application under `apps/website`.
|
||||
|
||||
**Backed by**:
|
||||
- `apps/website/package.json`
|
||||
- `apps/website/astro.config.mjs`
|
||||
- `apps/website/src/`
|
||||
- `apps/website/public/`
|
||||
- Website build output directory (implementation-specific, app-local)
|
||||
|
||||
**Key fields / responsibilities**:
|
||||
- Public-facing pages and layouts
|
||||
- Static-first dev/build lifecycle
|
||||
- Website-owned public assets
|
||||
- No shared auth/session/runtime assumptions with the platform app
|
||||
|
||||
**Validation rules**:
|
||||
- Must run independently from the platform app
|
||||
- Must not depend on Blade, Filament, or Laravel sessions
|
||||
- Must not write into platform build-output directories
|
||||
|
||||
## 4. OfficialCommandModel
|
||||
|
||||
**Purpose**: The documented contract that tells contributors how to work from the repo root and from app-local directories.
|
||||
|
||||
**Backed by**:
|
||||
- Root `package.json` scripts
|
||||
- README command documentation
|
||||
- VS Code task entry points where relevant
|
||||
|
||||
**Key fields / responsibilities**:
|
||||
- Root install flow for JavaScript workspace dependencies
|
||||
- Root platform start command
|
||||
- Root website start command
|
||||
- Root combined parallel-dev command
|
||||
- Root website build command
|
||||
- Root platform frontend build command
|
||||
- App-local equivalents for `apps/platform` and `apps/website`
|
||||
|
||||
**Validation rules**:
|
||||
- Root commands orchestrate only and delegate to app-local logic
|
||||
- App-local commands remain valid and documented
|
||||
- No second undocumented “official” workflow is introduced
|
||||
|
||||
## 5. ToolingSurface
|
||||
|
||||
**Purpose**: Root-level automation and editor guidance that must understand the multi-app repo shape.
|
||||
|
||||
**Backed by**:
|
||||
- `README.md`
|
||||
- `Agents.md`
|
||||
- `GEMINI.md`
|
||||
- `.github/copilot-instructions.md`
|
||||
- `.vscode/tasks.json`
|
||||
- `.vscode/mcp.json`
|
||||
- `opencode.json`
|
||||
|
||||
**Key fields / responsibilities**:
|
||||
- Explain root entry model and app ownership
|
||||
- Keep Boost MCP explicitly scoped to the platform app
|
||||
- Provide official entry tasks or labels for platform, website, and parallel dev
|
||||
|
||||
**Validation rules**:
|
||||
- Tooling must not imply the website is a second Laravel app
|
||||
- Tooling must not hide the official root entry path
|
||||
- Platform-specific commands must remain clearly labeled as platform-specific
|
||||
|
||||
## 6. BuildBoundary
|
||||
|
||||
**Purpose**: The isolation contract between platform assets and website assets.
|
||||
|
||||
**Backed by**:
|
||||
- Platform Vite output paths
|
||||
- Website build output paths
|
||||
- Ignore files and docs
|
||||
|
||||
**Key fields / responsibilities**:
|
||||
- Platform frontend artifacts remain under `apps/platform`
|
||||
- Website build artifacts remain under `apps/website`
|
||||
- Root build commands invoke app-local builds without cross-writing outputs
|
||||
|
||||
**Validation rules**:
|
||||
- Building the website must not overwrite or depend on platform artifacts
|
||||
- Building platform frontend assets must not overwrite or depend on website artifacts
|
||||
- Ignore files must cover both apps' dependency and build outputs
|
||||
|
||||
## Relationships
|
||||
|
||||
- `RootWorkspace` orchestrates `PlatformApp` and `WebsiteApp`.
|
||||
- `OfficialCommandModel` is owned by `RootWorkspace` and delegates into `PlatformApp` and `WebsiteApp`.
|
||||
- `ToolingSurface` documents and automates `OfficialCommandModel`.
|
||||
- `BuildBoundary` constrains both `PlatformApp` and `WebsiteApp`.
|
||||
|
||||
## Out-of-scope Entities
|
||||
|
||||
The following are explicitly not introduced in this feature:
|
||||
|
||||
- Shared packages under `packages/`
|
||||
- A docs application
|
||||
- A customer or auditor application
|
||||
- Shared auth/session infrastructure
|
||||
- New database entities or runtime-persisted domain truth
|
||||
260
specs/183-website-workspace-foundation/plan.md
Normal file
260
specs/183-website-workspace-foundation/plan.md
Normal file
@ -0,0 +1,260 @@
|
||||
# Implementation Plan: Website / Workspace Foundation
|
||||
|
||||
**Branch**: `183-website-workspace-foundation` | **Date**: 2026-04-08 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/spec.md`
|
||||
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/spec.md` and repo-context planning for the first real multi-app workspace slice.
|
||||
|
||||
## Summary
|
||||
|
||||
Introduce the first true multi-app foundation by adding a public website application under `apps/website` while keeping the existing Laravel platform stable under `apps/platform`. The implementation uses a minimal root orchestration model: one official Node workspace standard at repo root, one static-first website runtime, thin root scripts that orchestrate instead of re-implementing app logic, and a clear split between repo-level metadata, website runtime concerns, and platform runtime concerns.
|
||||
|
||||
Key approach: adopt `pnpm` workspaces as the official root package-manager standard, initialize the public website as an Astro app under `apps/website`, migrate the platform's Node command surface from npm to pnpm so the repo has one official JavaScript package-manager model, keep the platform Sail-first and Docker-backed, keep the website outside Sail in this first slice, and update only the root docs, tooling, and tasks that need multi-app awareness. The plan explicitly avoids shared packages, Turbo or Nx, a docs app, a customer app, a generalized app-runner framework, or any new TenantPilot product behavior.
|
||||
|
||||
The feature leaves Filament v5 on Livewire v4 unchanged, keeps panel providers registered in `apps/platform/bootstrap/providers.php`, does not add or alter globally searchable resources, introduces no destructive operator actions, and preserves the existing deploy-time `cd apps/platform && php artisan filament:assets` responsibility for platform assets.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: PHP 8.4.15 and Laravel 12 for `apps/platform`; Node.js 20+ with pnpm 10 workspace tooling; Astro v6 for `apps/website`; Bash and Docker Compose for root orchestration
|
||||
**Primary Dependencies**: `laravel/framework`, `filament/filament`, `livewire/livewire`, `laravel/sail`, `vite`, `tailwindcss`, `pnpm` workspaces, Astro, existing `./scripts/platform-sail` wrapper, repo-root Docker Compose
|
||||
**Storage**: Existing PostgreSQL, Redis, and filesystem storage for `apps/platform`; static build artifacts for `apps/website`; repository-managed workspace manifests and docs; no new database persistence
|
||||
**Testing**: Existing Pest v4 platform tests through Sail; website boot/build smoke; root command smoke; parallel-run and build-isolation validation; targeted task and MCP smoke where tooling changes
|
||||
**Target Platform**: macOS and Linux developer machines, Dockerized Laravel platform runtime, Node-based static public website runtime, Dokploy-style container deployment for the platform and static-site deployment for the website
|
||||
**Project Type**: Multi-app repo with repo-root orchestration, one Laravel platform app, and one static-first public website app
|
||||
**Performance Goals**: Preserve current platform boot/build behavior; keep website dev/build lightweight; allow platform and website to run in parallel on distinct ports with no cross-app artifact pollution
|
||||
**Constraints**: One official workspace standard only; no shared packages; no docs/customer/API surfaces; no website embedding into Blade or Filament; no root-level monorepo framework; keep platform Sail-first; root orchestrates while apps execute
|
||||
**Scale/Scope**: Two first-class applications under `apps/`, root orchestration manifests and scripts, documentation and task updates, and smoke validation across local boot, coexistence, and build separation
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.*
|
||||
|
||||
| Principle | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| Inventory-first | Pass | No inventory, snapshot, or backup truth changes; this is repo topology and runtime orchestration only |
|
||||
| Read/write separation | Pass | No new product mutation flow, operator write surface, or external write behavior is introduced |
|
||||
| Graph contract path | Pass | No Microsoft Graph calls or contract-registry changes are in scope |
|
||||
| Deterministic capabilities | Pass | Capability derivation and registries remain unchanged |
|
||||
| RBAC-UX planes and 404 vs 403 | Pass | `/admin`, `/admin/t/{tenant}/...`, and `/system` authorization semantics remain unchanged |
|
||||
| Workspace isolation | Pass | No new workspace-scoped data access or workspace routing behavior is introduced |
|
||||
| Tenant isolation | Pass | No tenant-owned routes, queries, or UI semantics are broadened |
|
||||
| Global search safety | Pass | No resource or global-search behavior changes are planned |
|
||||
| Dangerous and destructive confirmations | Pass | No new destructive operator actions are introduced |
|
||||
| Run observability | Pass | No new long-running product operations or `OperationRun` flows are introduced |
|
||||
| Ops-UX 3-surface feedback | Pass | Not applicable because no operation UX is added or changed |
|
||||
| Data minimization | Pass | No new secrets, logs, payload mirrors, or persisted product truth are added |
|
||||
| Proportionality (PROP-001) | Pass | The design adds only one website app and the minimum root orchestration needed to support it |
|
||||
| No premature abstraction (ABSTR-001) | Pass | The plan explicitly rejects Turbo, Nx, packages, a generic app-runner wrapper, and a generalized Sail abstraction |
|
||||
| Persisted truth (PERSIST-001) | Pass | Only repository artifacts are added; no new application tables or persisted domain entities |
|
||||
| Behavioral state (STATE-001) | Pass | No new domain status or reason-code family is introduced |
|
||||
| UI semantics (UI-SEM-001) | Pass | No new operator semantic layer is introduced; the website is a separate public app |
|
||||
| Filament-native UI (UI-FIL-001) | Pass | Platform Filament surfaces stay unchanged |
|
||||
| Filament v5 / Livewire v4 compliance | Pass | Platform remains on Filament v5 with Livewire v4; the website app does not affect that stack |
|
||||
| Provider registration location | Pass | Provider registration remains in `apps/platform/bootstrap/providers.php` |
|
||||
| Global search hard rule | Pass | No globally searchable resource gains or losses are introduced |
|
||||
| Asset strategy | Pass | Platform assets remain app-local and keep the `filament:assets` deploy step; website assets build independently from `apps/website` |
|
||||
| Testing plan | Pass | The plan includes platform regression smoke, website boot/build smoke, root command smoke, and coexistence validation |
|
||||
|
||||
## Phase 0 Research
|
||||
|
||||
Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/research.md`.
|
||||
|
||||
Key decisions:
|
||||
|
||||
- Adopt `pnpm` workspaces as the official JavaScript package-manager standard for the multi-app repo. The root receives `package.json` plus `pnpm-workspace.yaml`, and the platform's Node command surface migrates from npm to pnpm so the repo has one official package-manager story.
|
||||
- Use Astro v6 as the website stack because the spec explicitly wants a public-surface, static-first foundation with minimal runtime coupling.
|
||||
- Keep the platform Sail-first and Docker-backed, but do not Dockerize the website in this first slice. The website should run as a plain Node app to keep the first multi-app step proportional.
|
||||
- Keep `./scripts/platform-sail` as a platform-only compatibility helper. Do not introduce a generic `scripts/sail <app>` abstraction because only one app uses Sail today.
|
||||
- Keep Boost MCP and Laravel-specific editor integration platform-only. The website app is not a second Laravel runtime in this slice, so `.vscode/mcp.json` and `opencode.json` only need clearer scoping, not a second Boost server.
|
||||
- Limit root task updates to the official entry tasks and any affected labels or notes. This slice does not justify a wholesale task-system rewrite.
|
||||
|
||||
## Phase 1 Design
|
||||
|
||||
Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/183-website-workspace-foundation/`:
|
||||
|
||||
- `data-model.md`: repository-artifact and runtime-boundary model for root orchestration, platform app, website app, and tooling surfaces
|
||||
- `contracts/workspace-command-model.md`: canonical root and app-local command contract for platform, website, and parallel local development
|
||||
- `contracts/coexistence-smoke.openapi.yaml`: HTTP and orchestration smoke contract for website/platform coexistence
|
||||
- `quickstart.md`: implementation, validation, and rollout checklist for the workspace foundation
|
||||
|
||||
Design decisions:
|
||||
|
||||
- The root owns JavaScript workspace orchestration, but PHP and Laravel runtime ownership stays inside `apps/platform`.
|
||||
- The official root command model is intentionally small: install workspace dependencies, start the platform, start the website, start both, build the website, and build platform frontend assets.
|
||||
- The platform retains its current Docker Compose topology and `./scripts/platform-sail` wrapper. The website does not join Docker Compose in this slice.
|
||||
- The root does not introduce `packages/`, shared tokens, shared components, or cross-app runtime modules.
|
||||
- Root documentation and tooling are updated only where multi-app awareness is now necessary: README, Agents/GEMINI/Copilot guidance, entry tasks, and root-level config that references the platform as the only app.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/183-website-workspace-foundation/
|
||||
├── spec.md
|
||||
├── plan.md
|
||||
├── research.md
|
||||
├── data-model.md
|
||||
├── quickstart.md
|
||||
├── contracts/
|
||||
│ ├── workspace-command-model.md
|
||||
│ └── coexistence-smoke.openapi.yaml
|
||||
├── checklists/
|
||||
│ └── requirements.md
|
||||
└── tasks.md
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```text
|
||||
repo-root/
|
||||
├── apps/
|
||||
│ ├── platform/
|
||||
│ │ ├── app/
|
||||
│ │ ├── bootstrap/
|
||||
│ │ ├── config/
|
||||
│ │ ├── database/
|
||||
│ │ ├── public/
|
||||
│ │ ├── resources/
|
||||
│ │ ├── routes/
|
||||
│ │ ├── storage/
|
||||
│ │ ├── tests/
|
||||
│ │ ├── artisan
|
||||
│ │ ├── composer.json
|
||||
│ │ ├── package.json
|
||||
│ │ └── vite.config.js
|
||||
│ └── website/
|
||||
│ ├── package.json
|
||||
│ ├── astro.config.mjs
|
||||
│ ├── public/
|
||||
│ └── src/
|
||||
├── docs/
|
||||
├── specs/
|
||||
├── scripts/
|
||||
├── .specify/
|
||||
├── .github/
|
||||
├── .vscode/
|
||||
├── docker-compose.yml
|
||||
├── package.json
|
||||
├── pnpm-workspace.yaml
|
||||
├── README.md
|
||||
├── Agents.md
|
||||
├── GEMINI.md
|
||||
├── boost.json
|
||||
└── opencode.json
|
||||
```
|
||||
|
||||
**Structure Decision**: Repo-root workspace orchestration plus two app roots under `apps/`: the existing Laravel platform and a new Astro website. No `packages/` layer, no docs app, and no generalized monorepo framework are introduced.
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Phase A — Establish The Official Root Workspace Standard
|
||||
|
||||
**Goal**: Make the repo root the canonical JavaScript workspace entry point without turning it into an application runtime.
|
||||
|
||||
| Step | Area | Change |
|
||||
|------|------|--------|
|
||||
| A.1 | Workspace manifests | Add a minimal root `package.json` and `pnpm-workspace.yaml` for `apps/*` |
|
||||
| A.2 | Package-manager contract | Declare pnpm as the official JS package-manager standard and remove the implicit npm-only assumption from root docs and tooling |
|
||||
| A.3 | Lockfile model | Replace per-app `package-lock.json` usage for maintained app packages with one root `pnpm-lock.yaml` |
|
||||
| A.4 | Root scripts | Define thin root scripts for platform start, website start, parallel dev, website build, and platform frontend build |
|
||||
|
||||
### Phase B — Align The Platform App With The Workspace Standard
|
||||
|
||||
**Goal**: Keep `apps/platform` stable while letting it participate in the official pnpm-based workspace model.
|
||||
|
||||
| Step | Area | Change |
|
||||
|------|------|--------|
|
||||
| B.1 | Platform package manifest | Update `apps/platform/package.json` scripts to work under pnpm instead of npm-only assumptions |
|
||||
| B.2 | Composer scripts | Adjust `apps/platform/composer.json` Node-invoking scripts from `npm` to `pnpm` where they are part of the supported workflow |
|
||||
| B.3 | Sail runtime path | Keep `./scripts/platform-sail` and existing Compose wiring; rely on Corepack/pnpm availability inside Sail instead of building a new orchestration wrapper |
|
||||
| B.4 | Asset isolation | Preserve platform asset outputs under `apps/platform/public/build` and keep deploy-time `php artisan filament:assets` unchanged |
|
||||
|
||||
### Phase C — Create The Website App As A Separate Public Runtime
|
||||
|
||||
**Goal**: Introduce `apps/website` as a real standalone app with its own dev and build lifecycle.
|
||||
|
||||
| Step | Area | Change |
|
||||
|------|------|--------|
|
||||
| C.1 | Website scaffold | Create `apps/website` with Astro config, package manifest, `src/`, and `public/` |
|
||||
| C.2 | Public pages | Add the narrow initial public site structure needed for the foundation slice, without CMS/blog/docs/customer scope |
|
||||
| C.3 | Dev/build scripts | Ensure website dev and build commands run from root orchestration and app-local commands alike |
|
||||
| C.4 | Runtime separation | Keep website ports, environment assumptions, and build output isolated from the platform app |
|
||||
|
||||
### Phase D — Update Root Orchestration, Tooling, And Docs
|
||||
|
||||
**Goal**: Make the repo entry path obvious and keep automation aligned with the new topology.
|
||||
|
||||
| Step | Area | Change |
|
||||
|------|------|--------|
|
||||
| D.1 | README and architecture notes | Document the multi-app topology, official command model, and app-local ownership clearly |
|
||||
| D.2 | Agent and editor guidance | Update `Agents.md`, `GEMINI.md`, `.github/copilot-instructions.md`, and related guidance where root multi-app knowledge now matters |
|
||||
| D.3 | VS Code and root tooling | Add or adjust official entry tasks for platform, website, and parallel dev; keep Boost MCP platform-only but document that scope explicitly |
|
||||
| D.4 | Ignore and repo hygiene | Update ignore files and related repo metadata for `apps/website`, root lockfiles, and website build artifacts |
|
||||
|
||||
### Phase E — Validate Coexistence And Build Separation
|
||||
|
||||
**Goal**: Prove the multi-app repo behaves coherently before implementation is considered complete.
|
||||
|
||||
| Step | Area | Change |
|
||||
|------|------|--------|
|
||||
| E.1 | Platform stability | Verify existing platform boot paths and focused regression tests still pass |
|
||||
| E.2 | Website boot | Verify the website starts independently and is reachable on its own dev port |
|
||||
| E.3 | Parallel dev | Verify the platform and website can run together without port or artifact collisions |
|
||||
| E.4 | Build separation | Verify website build outputs remain isolated and platform frontend build still works independently |
|
||||
| E.5 | Documentation usability | Verify a contributor can follow the updated root entry docs without hidden steps |
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### D-001 — pnpm Becomes The One Official JavaScript Workspace Standard
|
||||
|
||||
The repo currently has only `apps/platform/package.json` plus a tracked `package-lock.json`, but Spec 183 requires one clear workspace/package-manager standard. pnpm workspaces give the minimal root construct needed for multi-app orchestration without requiring a heavier monorepo framework.
|
||||
|
||||
### D-002 — The Website Is A Static-First Astro App, Not A Second Laravel Runtime
|
||||
|
||||
The spec calls for a public website foundation, not another back-office application. Astro fits the static-first, public-surface constraint and avoids accidental coupling to platform sessions, Blade, Filament, or Laravel-specific runtime assumptions.
|
||||
|
||||
### D-003 — The Platform Stays Sail-First; The Website Does Not Join Docker In V1
|
||||
|
||||
The current Compose file and wrapper are already platform-specific and stable. Dockerizing the website now would add extra service orchestration, port strategy, and deployment assumptions that the spec explicitly tries to avoid in the first slice.
|
||||
|
||||
### D-004 — Root Scripts Orchestrate; App Logic Stays In The Apps
|
||||
|
||||
The root will provide the official entry scripts, but the platform keeps its app-local Sail and Composer logic, and the website keeps its app-local Astro logic. Root scripts are thin delegators, not a new orchestration framework.
|
||||
|
||||
### D-005 — No Shared Packages Or Generic App Wrappers In This Slice
|
||||
|
||||
This slice deliberately rejects `packages/`, shared token libraries, a generalized `scripts/sail <app>` abstraction, Turbo, Nx, and any cross-app build framework. Those additions would solve hypothetical future variance rather than the current concrete need.
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
| Risk | Impact | Likelihood | Mitigation |
|
||||
|------|--------|------------|------------|
|
||||
| pnpm migration breaks existing platform frontend commands or Composer scripts | High | Medium | Update platform `package.json` and `composer.json` together, and verify pnpm inside Sail before relying on it |
|
||||
| Contributors confuse root commands, app-local commands, and compatibility helpers | High | Medium | Publish one root command contract and keep app-local commands documented as secondary but valid |
|
||||
| Website dev port collides with current platform or Vite usage | Medium | Medium | Reserve a distinct website port and document override rules in quickstart and root scripts |
|
||||
| Root tooling remains platform-only in ways that confuse contributors after website arrives | Medium | High | Update README, task entry points, and agent guidance in the same slice as the website introduction |
|
||||
| The slice drifts into packages, shared tokens, or a docs app | High | Medium | Treat all extra surfaces and packages as explicit non-goals and block them in review |
|
||||
| Deployment assumptions for the website are overbuilt too early | Medium | Medium | Keep website deployment guidance minimal and static-site oriented, separate from the platform's Dokploy flow |
|
||||
|
||||
## Test Strategy
|
||||
|
||||
- Keep platform regression coverage focused: run the minimum representative Sail-driven Pest tests that prove the platform remains stable after the workspace changes.
|
||||
- Validate platform boot via existing local health and login surfaces such as `/up` and `/admin/login` after root/workspace changes land.
|
||||
- Validate website boot independently on its own dev server and verify it remains reachable without the platform app running.
|
||||
- Validate root entry commands for website-only, platform-only, and combined local development flows.
|
||||
- Validate platform frontend build and website build independently, ensuring outputs remain in their app-local directories.
|
||||
- Validate at least one affected VS Code task or root tooling entry path so editor automation does not drift behind the repo topology.
|
||||
- Reconfirm Filament v5 and Livewire v4 compliance by leaving the platform stack untouched and ensuring provider registration remains in `apps/platform/bootstrap/providers.php`.
|
||||
- Preserve the platform asset deployment contract by keeping `cd apps/platform && php artisan filament:assets` in deployment guidance.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
No constitution violation or exemption is planned. The feature intentionally limits complexity to one new app plus the minimum workspace contract needed to support it.
|
||||
|
||||
## Proportionality Review
|
||||
|
||||
- **Current operator problem**: The repo needs a public website surface now, but still behaves operationally like a single-app workspace. That makes local setup, docs, and tooling inconsistent the moment a second app is added.
|
||||
- **Existing structure is insufficient because**: `apps/platform` is correctly isolated, but the repo root still lacks a real workspace standard, root command model, and second-app boundary.
|
||||
- **Narrowest correct implementation**: Add one website app, one official root workspace standard, a thin root orchestration layer, and only the documentation and tooling updates required to make that structure usable.
|
||||
- **Ownership cost created**: One additional app lifecycle, one shared JS workspace lockfile, root script maintenance, and multi-app smoke validation.
|
||||
- **Alternative intentionally rejected**: Embedding the website into Laravel, keeping npm for the platform while adding pnpm only for the website, or introducing shared packages and monorepo frameworks immediately. Each alternative either violates the one-standard rule or adds speculative complexity.
|
||||
- **Release truth**: Current-release infrastructure truth for the first public website surface, not future-only preparation.
|
||||
72
specs/183-website-workspace-foundation/quickstart.md
Normal file
72
specs/183-website-workspace-foundation/quickstart.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Quickstart: Website / Workspace Foundation
|
||||
|
||||
## Goal
|
||||
|
||||
Implement and validate the first multi-app workspace slice with one stable platform app and one new public website app.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js with Corepack available on the host
|
||||
- PHP and Composer prerequisites for `apps/platform`
|
||||
- Docker / Docker Compose for the Sail-backed platform runtime
|
||||
|
||||
## 1. Bootstrap The Workspace
|
||||
|
||||
1. Enable Corepack on the host if needed.
|
||||
2. Install root workspace dependencies with pnpm.
|
||||
3. Install or confirm platform PHP dependencies in `apps/platform`.
|
||||
|
||||
## 2. Start The Platform App
|
||||
|
||||
1. Use the official root platform command, or the documented app-local equivalent.
|
||||
2. Confirm the platform health endpoint responds.
|
||||
3. Confirm the platform admin login route remains reachable.
|
||||
|
||||
## 3. Start The Website App
|
||||
|
||||
1. Use the official root website command, or the documented app-local equivalent.
|
||||
2. Confirm the website responds on its own dev port.
|
||||
3. Confirm the website does not require the platform app to serve its public pages.
|
||||
|
||||
## Port Override Path
|
||||
|
||||
1. If the platform port is already occupied, rerun the platform flow with `APP_PORT=<port>` and, if needed, `VITE_PORT=<port>`.
|
||||
2. If the website port is already occupied, rerun the website flow with `WEBSITE_PORT=<port>` from the root command path, or use the app-local Astro command with `--port <port>`.
|
||||
3. If both apps run together, confirm the overridden ports still keep platform and website separated and documented.
|
||||
|
||||
## 4. Validate Parallel Local Development
|
||||
|
||||
1. Start the platform and the website together using the official root orchestration path.
|
||||
2. Confirm there is no obvious port conflict between the platform and the website.
|
||||
3. If a default port is occupied, confirm the documented override path works for the affected app.
|
||||
4. Confirm editing one app does not require restarting the other app.
|
||||
|
||||
## 5. Validate Build Separation
|
||||
|
||||
1. Run the website build through the official root command.
|
||||
2. Run the platform frontend build through the official root command.
|
||||
3. Confirm each build writes only to its own app-owned output paths.
|
||||
|
||||
## 6. Validate Tooling And Docs
|
||||
|
||||
1. Read the updated root README and confirm the multi-app entry path is clear.
|
||||
2. Verify at least one affected VS Code task or root automation path still behaves correctly.
|
||||
3. Confirm MCP guidance remains platform-only and does not imply the website is a Laravel app.
|
||||
4. Confirm the documented port-override path is described consistently between the README and the command contract.
|
||||
|
||||
## 7. Validate Platform Stability
|
||||
|
||||
1. Run the minimum representative Sail-based platform regression tests needed to prove workspace changes did not destabilize the app.
|
||||
2. Confirm Filament v5 on Livewire v4 remains untouched.
|
||||
3. Confirm panel provider registration still lives in `apps/platform/bootstrap/providers.php`.
|
||||
4. Confirm no globally searchable resource behavior was changed by this slice.
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- Root workspace manifests exist and are documented.
|
||||
- `apps/website` exists as a real standalone app.
|
||||
- Platform boot remains stable.
|
||||
- Website boot remains independent.
|
||||
- Root commands for platform, website, and parallel local development are clear and usable.
|
||||
- Website and platform builds remain isolated.
|
||||
- No shared package layer or extra product surface was introduced.
|
||||
86
specs/183-website-workspace-foundation/research.md
Normal file
86
specs/183-website-workspace-foundation/research.md
Normal file
@ -0,0 +1,86 @@
|
||||
# Research: Website / Workspace Foundation
|
||||
|
||||
## Decision 1: Use pnpm workspaces as the official JavaScript workspace standard
|
||||
|
||||
**Decision**: Adopt pnpm 10 workspaces with a root `package.json` and `pnpm-workspace.yaml` as the official JavaScript package-manager and workspace model for the repo.
|
||||
|
||||
**Rationale**:
|
||||
- Spec 183 requires exactly one official workspace/package-manager standard.
|
||||
- The repo currently has no root workspace manifest and only one tracked JavaScript package manifest under `apps/platform`, so the first multi-app slice needs an explicit root contract.
|
||||
- pnpm workspaces require only a root `pnpm-workspace.yaml` and support a single shared lockfile, which keeps the first multi-app step narrow.
|
||||
- Official pnpm workspace guidance confirms that workspaces are a built-in fit for multi-project repositories and that the root workspace file is the canonical entry point.
|
||||
- The current environment already supports the migration path: host Node has Corepack available, and the running Sail container exposes both Corepack and pnpm.
|
||||
|
||||
**Alternatives considered**:
|
||||
- Keep npm for `apps/platform` and introduce pnpm only for `apps/website`: rejected because it violates the spec's one-official-standard rule and creates an ambiguous dual model.
|
||||
- Use npm workspaces: rejected because the spec's recommended direction is pnpm and pnpm offers the cleaner shared-lockfile monorepo path for this repo shape.
|
||||
- Use Yarn or Bun workspaces: rejected because they add a new toolchain direction with no repo-specific advantage here.
|
||||
- Introduce Turbo or Nx immediately: rejected as premature orchestration complexity for a two-app repo.
|
||||
|
||||
## Decision 2: Use Astro as the website stack
|
||||
|
||||
**Decision**: Introduce `apps/website` as an Astro v6 application.
|
||||
|
||||
**Rationale**:
|
||||
- The feature is explicitly a public website foundation, not a second authenticated product surface.
|
||||
- Astro is designed for public-facing sites and supports the static-first model the spec asks for.
|
||||
- Astro keeps the website runtime lightweight while avoiding accidental coupling to Blade, Filament, shared sessions, or Laravel panel assumptions.
|
||||
- The docs emphasize project structure, dev/build flows, layouts, pages, and static-site friendly features, which align with this slice.
|
||||
|
||||
**Alternatives considered**:
|
||||
- Build the website inside Laravel Blade: rejected because the spec explicitly forbids platform embedding and wants separate runtimes.
|
||||
- Use another JavaScript SSR-heavy app shell such as Next.js or Nuxt: rejected because this slice does not need a heavier runtime or server coupling.
|
||||
- Use a raw Vite-only site: rejected because Astro provides a clearer public-site application structure without forcing a custom content/runtime foundation.
|
||||
|
||||
## Decision 3: Keep the platform Sail-first and do not Dockerize the website in V1
|
||||
|
||||
**Decision**: `apps/platform` remains the only Sail/Docker-backed application in this slice; `apps/website` runs as a plain Node application for local development and static builds.
|
||||
|
||||
**Rationale**:
|
||||
- The current root `docker-compose.yml` and `./scripts/platform-sail` wrapper are explicitly platform-specific and already stable.
|
||||
- Dockerizing the website immediately would require a second service strategy, new port policy, and broader deployment assumptions that the spec does not require.
|
||||
- The website does not need PostgreSQL, Redis, queues, or Laravel runtime services in this foundation slice.
|
||||
- Keeping the website outside Sail preserves the root-orchestrates/apps-execute model while minimizing cross-app runtime coupling.
|
||||
|
||||
**Alternatives considered**:
|
||||
- Add a second Docker Compose service for the website now: rejected as unnecessary orchestration growth in the first multi-app slice.
|
||||
- Move both apps to host-only local dev: rejected because the platform is already Sail-first and that contract should remain stable.
|
||||
|
||||
## Decision 4: Keep root orchestration thin and app-specific wrappers narrow
|
||||
|
||||
**Decision**: Add only thin root scripts for official entry points and keep `./scripts/platform-sail` as a platform-only compatibility wrapper instead of generalizing it to a multi-app runner.
|
||||
|
||||
**Rationale**:
|
||||
- The repo has one Sail-backed app today. A generic `scripts/sail <app>` wrapper would be an abstraction with only one concrete user.
|
||||
- Spec 183 explicitly prefers minimal root orchestration and rejects premature shared layers or frameworkization.
|
||||
- Root scripts can delegate to `./scripts/platform-sail` for the platform and to `pnpm --dir apps/website ...` or workspace-filtered pnpm commands for the website without inventing a new app-runner subsystem.
|
||||
|
||||
**Alternatives considered**:
|
||||
- Introduce a generalized app-launch wrapper immediately: rejected under ABSTR-001 because there is not yet real variance across multiple Docker-backed apps.
|
||||
- Keep only app-local commands and document them: rejected because the spec requires an official root entry model.
|
||||
|
||||
## Decision 5: Update only the tooling that now needs multi-app awareness
|
||||
|
||||
**Decision**: Update root docs, entry tasks, and agent/editor guidance to reflect the new workspace model, while keeping Laravel-specific MCP integration platform-only.
|
||||
|
||||
**Rationale**:
|
||||
- `.vscode/mcp.json` and `opencode.json` currently point at the platform Boost MCP server only. That remains correct because the website is not a second Laravel runtime.
|
||||
- The repo's tasks and docs currently assume only the platform exists. Those surfaces need new multi-app awareness so contributors understand the official entry path.
|
||||
- A full task-system rewrite is not required to satisfy the spec. This slice only needs a clear, official root command surface and enough task/documentation updates to make it discoverable.
|
||||
|
||||
**Alternatives considered**:
|
||||
- Add a second Boost MCP server for the website: rejected because the website app is not a Laravel app.
|
||||
- Rename and rebuild every existing task in the repo: rejected because it is broader than the narrow workspace-foundation objective.
|
||||
|
||||
## Decision 6: Build isolation matters more than early shared code reuse
|
||||
|
||||
**Decision**: Accept small duplication between `apps/platform` and `apps/website`, and do not introduce `packages/`, shared design tokens, or shared UI primitives in this slice.
|
||||
|
||||
**Rationale**:
|
||||
- The current concrete problem is introducing a second app cleanly, not extracting shared code.
|
||||
- A shared layer would force versioning, ownership, and build-coupling decisions before the repo has even demonstrated repeated needs across more than one new app.
|
||||
- The spec explicitly states that duplication is acceptable in small amounts and that shared packages are a likely follow-up, not part of this slice.
|
||||
|
||||
**Alternatives considered**:
|
||||
- Create `packages/ui`, `packages/brand`, or shared Tailwind tokens now: rejected as future-facing complexity without proven repeated use.
|
||||
- Share platform assets or auth/session infrastructure with the website: rejected because the spec requires runtime separation.
|
||||
175
specs/183-website-workspace-foundation/spec.md
Normal file
175
specs/183-website-workspace-foundation/spec.md
Normal file
@ -0,0 +1,175 @@
|
||||
# Feature Specification: Website / Workspace Foundation
|
||||
|
||||
**Feature Branch**: `183-website-workspace-foundation`
|
||||
**Created**: 2026-04-08
|
||||
**Status**: Proposed
|
||||
**Input**: User description: "Introduce the first real multi-app foundation after the platform move to apps/platform by adding a public website app, minimal root orchestration, a clear command/workspace model, and strict separation between website, platform, and repo-wide meta-structures."
|
||||
|
||||
## Spec Scope Fields *(mandatory)*
|
||||
|
||||
- **Scope**: workspace
|
||||
- **Primary Routes**: Public website entry pages in the new website app; existing platform entry routes under `/admin` and `/system` remain unchanged; the root README and local development entry flow become the documented repo starting point.
|
||||
- **Data Ownership**: No new tenant-owned or workspace-owned application records are introduced; this slice adds repo/workspace configuration artifacts and a new website app source tree only.
|
||||
- **RBAC**: Public website pages are anonymous; existing platform and tenant membership/capability rules remain unchanged.
|
||||
|
||||
## Proportionality Review *(mandatory when structural complexity is introduced)*
|
||||
|
||||
- **New source of truth?**: Yes. The repo root becomes the canonical multi-app workspace entry point for orchestration and discovery.
|
||||
- **New persisted entity/table/artifact?**: Yes. The feature adds root workspace manifests/configuration and a new website app as versioned repository artifacts, but no new runtime business tables or persisted domain records.
|
||||
- **New abstraction?**: Yes. The feature introduces an explicit root orchestration model for multiple apps.
|
||||
- **New enum/state/reason family?**: No.
|
||||
- **New cross-domain UI framework/taxonomy?**: No.
|
||||
- **Current operator problem**: The product now needs a public website surface, but the repo still behaves like a single-app workspace. That makes website introduction ad hoc, hard to document, and easy to couple accidentally to the platform app.
|
||||
- **Existing structure is insufficient because**: `apps/platform` is now correctly isolated, but there is no official root command model, no second app boundary, and no repo-level convention that tells contributors how multiple apps coexist or how to run them safely in parallel.
|
||||
- **Narrowest correct implementation**: Add one real website app, one explicit workspace/orchestration model, and only the minimum root files and commands needed to run the platform, the website, or both.
|
||||
- **Ownership cost**: The repo gains one more app to maintain, one more local run/build flow, root-level documentation upkeep, and a small amount of multi-app tooling review and smoke-test surface.
|
||||
- **Alternative intentionally rejected**: Embedding the website into the platform app or introducing shared packages, docs, customer, or API surfaces immediately was rejected because those approaches either couple runtimes prematurely or add speculative structure without current-release value.
|
||||
- **Release truth**: Current-release truth. The public website is the next concrete surface the product needs; this is not future-only preparation.
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Start the Repo From One Clear Entry Model (Priority: P1)
|
||||
|
||||
A contributor needs to open the repository and immediately understand how to start the platform app, the website app, or both from one official documented entry path.
|
||||
|
||||
**Why this priority**: Without an official root entry model, every follow-up multi-app change becomes inconsistent, slows onboarding, and increases the risk of divergent local workflows.
|
||||
|
||||
**Independent Test**: A contributor can clone or open the repo, follow the root documentation, and use the official commands to start the platform, the website, or both without needing undocumented steps.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a contributor is at the repo root, **When** they follow the documented workspace entry flow, **Then** they can identify the official commands for platform-only, website-only, and parallel local development.
|
||||
2. **Given** both apps exist in the repo, **When** a contributor starts them through the official model, **Then** each app boots through its own app-local execution path while the root only orchestrates.
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - Work on the Website Independently (Priority: P2)
|
||||
|
||||
A contributor focused on the public website needs a real standalone website app that can run and build without requiring the platform runtime, shared sessions, or platform templating.
|
||||
|
||||
**Why this priority**: The website is the first new product surface after the platform extraction, so it must be able to evolve independently instead of being treated as a sidecar inside the platform app.
|
||||
|
||||
**Independent Test**: The website app can be started and built on its own, and the resulting public pages do not depend on the platform app being booted.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** the platform app is not running, **When** a contributor starts the website app, **Then** the website is locally reachable and serves its public pages without requiring platform authentication or server-side platform rendering.
|
||||
2. **Given** the website app is built, **When** the platform app remains untouched, **Then** the platform build/runtime outputs are unchanged and do not depend on website artifacts.
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - Preserve Platform Stability During the Multi-App Transition (Priority: P3)
|
||||
|
||||
A platform contributor needs the new multi-app setup to leave `apps/platform` functionally stable while documenting how the platform fits into the broader repo layout.
|
||||
|
||||
**Why this priority**: The workspace foundation is only useful if it enables expansion without destabilizing TenantPilot itself.
|
||||
|
||||
**Independent Test**: Existing platform startup and smoke checks continue to work after the workspace changes, and contributors can still use app-local platform commands while understanding the new root entry model.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** the repo has adopted the multi-app structure, **When** a contributor runs the documented platform workflow, **Then** the platform starts and behaves as before.
|
||||
2. **Given** the platform and website are developed in parallel, **When** both are started locally, **Then** there are no obvious runtime or build collisions between them.
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- A contributor has not installed the official workspace/package manager: the root documentation must identify the supported standard clearly and avoid leaving parallel unsupported root workflows ambiguous.
|
||||
- A default website port or platform-adjacent port is already in use: the official local-development guidance must make the conflict visible and describe the supported override path.
|
||||
- A contributor builds the website while stale platform frontend assets already exist: the build outputs must remain app-local and must not overwrite or rely on platform artifacts.
|
||||
- The platform app is temporarily unavailable: the website app must still start and build independently.
|
||||
- The website app is unavailable or not being worked on: the platform app must continue to support its established app-local workflow.
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
**Constitution alignment (required):** This feature introduces repo-level orchestration and a new public application surface, but it does not add Microsoft Graph calls, new tenant/workspace business persistence, `OperationRun` workflows, or authorization-plane changes. The key constitutional obligations are proportionality, explicit ownership of root-versus-app responsibilities, preservation of platform stability, and testable proof that the new multi-app structure remains intentionally narrow.
|
||||
|
||||
### Scope
|
||||
|
||||
**In scope**
|
||||
|
||||
- A real `apps/website` application for the public website.
|
||||
- A minimal root workspace and orchestration model for multiple apps.
|
||||
- One official workspace/package-manager standard for root orchestration.
|
||||
- One official root command model covering the platform, the website, and parallel local development.
|
||||
- Clear separation of build and runtime responsibilities between the root, the platform app, and the website app.
|
||||
- Documentation and tooling updates required to make the multi-app repo understandable and usable.
|
||||
- Smoke validation for website boot, platform stability, parallel local development, and build separation.
|
||||
|
||||
**Out of scope**
|
||||
|
||||
- `apps/docs`
|
||||
- `packages/*` shared packages
|
||||
- Shared design-token, UI, or content packages
|
||||
- Customer or auditor surfaces
|
||||
- Public API or developer portal work
|
||||
- CMS, blog, or content-engine expansion
|
||||
- TenantPilot domain feature changes
|
||||
- Large CI/CD re-architecture beyond the minimum documentation and tooling implications of this slice
|
||||
|
||||
### Architectural Commitments
|
||||
|
||||
- The repository MUST use one official root workspace/package-manager standard for this slice, applied consistently across root orchestration and the website app.
|
||||
- The public website MUST be introduced as a static-first standalone application under `apps/website`.
|
||||
- Root orchestration MUST remain minimal: the root defines the workspace, documents the official commands, and coordinates multi-app entry paths, while app-specific execution logic stays inside each app.
|
||||
- No shared package layer is introduced in this slice; small, local duplication between the platform and the website is acceptable until a real repeated need exists.
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- **FR-001**: The repository MUST expose a first-class multi-app topology with `apps/platform` and `apps/website` as the only application surfaces introduced by this slice.
|
||||
- **FR-002**: The root of the repository MUST provide the minimal workspace files required to make the official multi-app model explicit and usable.
|
||||
- **FR-003**: The repository MUST define a single official root command model that covers starting the platform app, starting the website app, starting both apps for parallel local development, building the website app, and building the platform frontend when needed.
|
||||
- **FR-004**: `apps/website` MUST be introduced as a real standalone app with its own source tree, public assets, local run flow, and build flow.
|
||||
- **FR-005**: The website app MUST remain a public-surface runtime and MUST NOT depend on Blade, Filament, platform sessions, shared platform cookies, or embedding inside the platform app.
|
||||
- **FR-006**: `apps/platform` MUST retain its existing app-local run and build workflows and MUST remain functionally stable under the new root model.
|
||||
- **FR-007**: Root orchestration MUST describe and coordinate app workflows, but app-local execution logic MUST continue to live inside the respective app directories.
|
||||
- **FR-008**: Website and platform local development MUST be able to run in parallel without shared build outputs, undocumented manual file shuffling, or cross-app runtime coupling.
|
||||
- **FR-009**: Website and platform build outputs MUST remain isolated so that building or cleaning one app does not overwrite, invalidate, or implicitly require artifacts from the other app.
|
||||
- **FR-010**: The root documentation MUST explain the repo structure, the purpose of `apps/platform` and `apps/website`, the official workspace standard, the official root commands, and the app-local command model.
|
||||
- **FR-011**: Tooling, editor, and agent instructions that rely on root-level repo knowledge MUST be updated where needed so they reflect the multi-app structure and the official root entry path.
|
||||
- **FR-012**: The website foundation introduced by this slice MUST remain intentionally narrow: public website pages and the supporting workspace foundation only, with no CMS or blog engine, docs surface, customer surface, API surface, or mandatory shared-package layer.
|
||||
- **FR-013**: The feature MUST not introduce any new shared package, additional top-level application surface, or domain feature change unless separately specified in a later spec.
|
||||
- **FR-014**: A smoke validation plan MUST verify platform stability, website boot, parallel local development, root orchestration usability, build separation, and documentation usability before the slice is considered complete.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
- The repo has a clear multi-app structure with `apps/platform` and `apps/website`.
|
||||
- A single official workspace/package-manager standard is defined and documented.
|
||||
- The minimal root orchestration files and commands exist and are understandable from the repo root.
|
||||
- The website app is independently runnable and buildable.
|
||||
- The platform app remains stable and functionally unchanged by the workspace introduction.
|
||||
- Platform and website can be developed locally in parallel.
|
||||
- Root documentation explains the multi-app model and the official entry path clearly.
|
||||
- No shared packages, docs surface, customer surface, or public API surface are introduced in this slice.
|
||||
- Smoke validation demonstrates coexistence and build/runtime isolation.
|
||||
|
||||
### Key Entities
|
||||
|
||||
- **Root Workspace**: The canonical repo-level contract that defines the official workspace standard, root orchestration files, and documented entry commands for the multi-app repo.
|
||||
- **Platform App**: The existing TenantPilot Laravel application under `apps/platform`, which remains operationally separate and functionally stable.
|
||||
- **Website App**: The new public-surface application under `apps/website`, intended for public product communication and independent local run/build workflows.
|
||||
- **Official Command Model**: The documented set of root and app-local commands that tells contributors how to start, build, and work on the platform app, the website app, or both together.
|
||||
- **Build/Runtime Boundary**: The separation rule that keeps dependencies, generated artifacts, ports, and runtime assumptions isolated between the platform and the website.
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: A contributor can identify where the platform lives, where the website lives, and which official commands to use from the repo root within 10 minutes using only the updated root documentation.
|
||||
- **SC-002**: Both apps can be started locally through the documented command model in the same development session with no unresolved port or runtime conflict beyond documented configuration overrides.
|
||||
- **SC-003**: The website can be built successfully without requiring the platform app to be running, and the platform can complete its documented build workflow without requiring website artifacts.
|
||||
- **SC-004**: Relevant existing platform startup and smoke checks continue to pass after the workspace foundation is introduced.
|
||||
- **SC-005**: Repo review after this slice shows exactly one new first-class application surface (`apps/website`) and zero newly introduced shared packages or adjacent product surfaces.
|
||||
- **SC-006**: A contributor can complete a platform-only workflow or a website-only workflow without starting the other app, except where the documentation explicitly states otherwise.
|
||||
|
||||
## Assumptions
|
||||
|
||||
- The public website starts as a lightweight public information surface rather than an authenticated customer, docs, or partner portal.
|
||||
- The platform application remains the canonical home for TenantPilot product logic; this slice only changes the repo and workspace foundation around it.
|
||||
- Parallel local development uses separate app runtimes and separate default ports.
|
||||
- Minor duplication between the platform and the website is acceptable until a real repeated need justifies a shared package.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- The platform extraction completed in Spec 182 remains intact and provides a stable `apps/platform` baseline.
|
||||
- Repo-level documentation, tasks, and agent/tooling files can be updated to reflect the multi-app entry model.
|
||||
- Local contributors can install the official workspace toolchain alongside the existing platform prerequisites.
|
||||
206
specs/183-website-workspace-foundation/tasks.md
Normal file
206
specs/183-website-workspace-foundation/tasks.md
Normal file
@ -0,0 +1,206 @@
|
||||
# Tasks: Website / Workspace Foundation
|
||||
|
||||
**Input**: Design documents from `/specs/183-website-workspace-foundation/`
|
||||
**Prerequisites**: `plan.md` (required), `spec.md` (required for user stories), `research.md`, `data-model.md`, `contracts/`, `quickstart.md`
|
||||
|
||||
**Tests**: Tests are REQUIRED for this feature. Use focused Pest coverage under `apps/platform/tests/Feature/WorkspaceFoundation/` plus contract-backed smoke validation from `specs/183-website-workspace-foundation/contracts/workspace-command-model.md`, `specs/183-website-workspace-foundation/contracts/coexistence-smoke.openapi.yaml`, and `specs/183-website-workspace-foundation/quickstart.md`.
|
||||
**Operations**: This feature does not introduce a new `OperationRun` type or change existing operations UX semantics. Coexistence, root-command, and build-isolation smoke validation is still required because the repo gains a second app runtime.
|
||||
**RBAC**: No authorization model changes are allowed. Validation must preserve existing `/admin`, `/admin/t/{tenant}/...`, and `/system` behavior exactly as-is.
|
||||
**Operator Surfaces**: No operator-surface redesign is part of this slice. Existing public, admin, tenant, and system surfaces must continue to render with the same routing and authorization semantics.
|
||||
**Filament UI Action Surfaces**: No new Filament action surfaces are introduced. Existing resources and pages must continue to work unchanged once the workspace foundation lands.
|
||||
**Filament UI UX-001**: No layout or information-architecture redesign is part of this feature. Filament panels, themes, and existing surface contracts must remain intact.
|
||||
**Badges**: No badge semantics change is planned. Existing badge rendering must continue to work after the workspace changes.
|
||||
|
||||
**Organization**: Tasks are grouped by user story so each story can be implemented and validated as an independent increment once the blocking workspace groundwork is complete.
|
||||
|
||||
## Phase 1: Setup (Shared Workspace Scaffolding)
|
||||
|
||||
**Purpose**: Prepare the repo root, the website app scaffold, and the focused test namespace before the blocking workspace conversion begins.
|
||||
|
||||
- [X] T001 Create the root workspace manifest scaffold in `package.json` and `pnpm-workspace.yaml`
|
||||
- [X] T002 [P] Create the website application scaffold directories in `apps/website/src/` and `apps/website/public/`
|
||||
- [X] T003 [P] Create the focused workspace foundation test namespace in `apps/platform/tests/Feature/WorkspaceFoundation/`
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: Complete the shared package-manager and repo-boundary work that all user stories depend on.
|
||||
|
||||
**⚠️ CRITICAL**: No user story work should begin until this phase is complete.
|
||||
|
||||
- [X] T004 Replace single-app npm assumptions with the shared pnpm workspace baseline by creating `pnpm-lock.yaml`, updating `apps/platform/package.json`, and removing tracked `apps/platform/package-lock.json`
|
||||
- [X] T005 [P] Align platform Composer Node scripts with pnpm in `apps/platform/composer.json`
|
||||
- [X] T006 [P] Align repo ignore and formatting rules for website and workspace artifacts in `.gitignore` and `.prettierignore`
|
||||
- [X] T007 [P] Add baseline platform boot smoke coverage for workspace changes in `apps/platform/tests/Feature/WorkspaceFoundation/PlatformBootSmokeTest.php`
|
||||
|
||||
**Checkpoint**: The repo now has one JavaScript workspace standard, one shared lockfile model, and baseline platform smoke coverage for the multi-app transition.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Start the Repo From One Clear Entry Model (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: Make the repo root the obvious and documented entry point for platform-only, website-only, and parallel local development.
|
||||
|
||||
**Independent Test**: From the repo root, a contributor can follow the updated docs and use the official commands to start the platform, the website, or both without undocumented steps.
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [X] T008 [US1] Implement the official root workspace scripts and package-manager declaration in `package.json`, aligned to `specs/183-website-workspace-foundation/contracts/workspace-command-model.md`
|
||||
- [X] T009 [P] [US1] Update the multi-app repo entry documentation and architecture overview in `README.md` and `docs/PROJECT_SUMMARY.md`
|
||||
- [X] T010 [P] [US1] Align human and assistant guidance with the multi-app command model in `Agents.md`, `GEMINI.md`, `.github/copilot-instructions.md`, and `.github/agents/copilot-instructions.md`
|
||||
- [X] T011 [US1] Add official root entry tasks and platform-only MCP scoping in `.vscode/tasks.json`, `.vscode/mcp.json`, and `opencode.json`, aligned to `specs/183-website-workspace-foundation/contracts/workspace-command-model.md`
|
||||
- [X] T012 [US1] Validate the platform-only, website-only, and parallel root entry flows, including the supported port-override path, against `specs/183-website-workspace-foundation/contracts/workspace-command-model.md` and `specs/183-website-workspace-foundation/quickstart.md`
|
||||
|
||||
**Checkpoint**: The repo root is now the documented primary entry path for the multi-app workspace.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - Work on the Website Independently (Priority: P2)
|
||||
|
||||
**Goal**: Introduce a real standalone public website app that can run and build without the platform runtime.
|
||||
|
||||
**Independent Test**: `apps/website` can start and build on its own, and its public pages render without the platform app running.
|
||||
|
||||
### Implementation for User Story 2
|
||||
|
||||
- [X] T013 [US2] Implement the standalone Astro website manifest and app configuration in `apps/website/package.json` and `apps/website/astro.config.mjs`
|
||||
- [X] T014 [P] [US2] Build the initial public website structure in `apps/website/src/layouts/BaseLayout.astro`, `apps/website/src/pages/index.astro`, and `apps/website/src/styles/global.css`
|
||||
- [X] T015 [P] [US2] Add website public assets and metadata files in `apps/website/public/favicon.svg` and `apps/website/public/robots.txt`
|
||||
- [X] T016 [US2] Validate standalone website boot, website-only build behavior, and the supported website port-override path against `specs/183-website-workspace-foundation/contracts/coexistence-smoke.openapi.yaml` and `specs/183-website-workspace-foundation/quickstart.md`
|
||||
|
||||
**Checkpoint**: The public website now exists as a real app and can be developed independently from the platform.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 - Preserve Platform Stability During the Multi-App Transition (Priority: P3)
|
||||
|
||||
**Goal**: Keep `apps/platform` stable and prove the platform still boots, builds, and coexists cleanly with the website under the new workspace model.
|
||||
|
||||
**Independent Test**: Focused platform regression tests still pass, the platform dev/build workflow remains valid under pnpm, and platform plus website can run together without build or runtime collisions.
|
||||
|
||||
### Tests for User Story 3
|
||||
|
||||
- [X] T017 [P] [US3] Add platform workspace compatibility smoke coverage in `apps/platform/tests/Feature/WorkspaceFoundation/PlatformWorkspaceCompatibilityTest.php`
|
||||
|
||||
### Implementation for User Story 3
|
||||
|
||||
- [X] T018 [US3] Finalize pnpm-based platform frontend scripts in `apps/platform/package.json` and `apps/platform/composer.json`
|
||||
- [X] T019 [P] [US3] Preserve platform compatibility-helper and deployment asset guidance in `scripts/platform-sail` and `README.md`
|
||||
- [X] T020 [P] [US3] Document multi-app platform isolation and rollout notes in `docs/HANDOVER.md` and `docs/PROJECT_SUMMARY.md`
|
||||
- [X] T021 [US3] Validate focused platform regression, parallel local development, build separation, and the supported platform or website port-override path against `specs/183-website-workspace-foundation/contracts/workspace-command-model.md`, `specs/183-website-workspace-foundation/contracts/coexistence-smoke.openapi.yaml`, and `specs/183-website-workspace-foundation/quickstart.md`
|
||||
|
||||
**Checkpoint**: The platform remains stable under the new workspace model, and coexistence with the website is proven.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Remove stale single-app assumptions, normalize manifests, and finish the final validation pass.
|
||||
|
||||
- [X] T022 [P] Remove stale npm-only and single-app references across `README.md`, `Agents.md`, `GEMINI.md`, `.github/copilot-instructions.md`, `.github/agents/copilot-instructions.md`, `.vscode/tasks.json`, `.vscode/mcp.json`, and `opencode.json`
|
||||
- [X] T023 [P] Normalize the final workspace manifests and app package files in `package.json`, `pnpm-workspace.yaml`, `apps/platform/package.json`, and `apps/website/package.json`
|
||||
- [X] T024 [P] Run the focused workspace foundation Pest suite in `apps/platform/tests/Feature/WorkspaceFoundation/`
|
||||
- [X] T025 Run the full contract-backed smoke validation, including the supported port-override path, and capture final coexistence evidence from `specs/183-website-workspace-foundation/contracts/workspace-command-model.md`, `specs/183-website-workspace-foundation/contracts/coexistence-smoke.openapi.yaml`, and `specs/183-website-workspace-foundation/quickstart.md`
|
||||
- [X] T026 [P] Audit the final repo topology and slice scope against `specs/183-website-workspace-foundation/spec.md`, `package.json`, `pnpm-workspace.yaml`, `apps/`, and `README.md` to confirm no `packages/*` shared package layer, no shared design-token, UI, or content packages, no `apps/docs`, no customer or auditor surface, no public API or developer portal work, no CMS, blog, or content-engine expansion, no TenantPilot domain feature changes, no large CI or CD re-architecture beyond this slice, and no additional app surfaces were introduced
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Setup (Phase 1)**: Starts immediately and prepares the repo and test scaffolding.
|
||||
- **Foundational (Phase 2)**: Depends on Setup and blocks all user stories until the workspace standard, lockfile model, and baseline smoke coverage are in place.
|
||||
- **User Story 1 (Phase 3)**: Starts after Foundational and establishes the official root entry model.
|
||||
- **User Story 2 (Phase 4)**: Starts after Foundational and can proceed in parallel with User Story 1, but its final validation should use the root entry model created in User Story 1.
|
||||
- **User Story 3 (Phase 5)**: Starts after Foundational and should finish after User Stories 1 and 2 because it validates the final combined platform-plus-website setup.
|
||||
- **Polish (Phase 6)**: Starts after all desired user stories are complete.
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **US1**: Depends only on Setup and Foundational work.
|
||||
- **US2**: Depends on Setup and Foundational work; final root-command validation reuses US1.
|
||||
- **US3**: Depends on Foundational work and validates the final integrated outcome of US1 and US2.
|
||||
|
||||
### Within Each User Story
|
||||
|
||||
- Shared workspace manifests and package-manager conversion must land before docs or tasks that declare them as canonical.
|
||||
- Website app config should land before website pages and assets.
|
||||
- Platform stability validation should run after root scripts, website app setup, and pnpm-based platform scripts are complete.
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- `T002` and `T003` can run in parallel during Setup.
|
||||
- `T005`, `T006`, and `T007` can run in parallel once `T004` establishes the shared workspace baseline.
|
||||
- `T009` and `T010` can run in parallel for US1.
|
||||
- `T014` and `T015` can run in parallel for US2 once `T013` establishes the website config.
|
||||
- `T017`, `T019`, and `T020` can run in parallel for US3.
|
||||
- `T022`, `T023`, `T024`, and `T026` can run in parallel during Polish.
|
||||
|
||||
---
|
||||
|
||||
## Parallel Example: User Story 1
|
||||
|
||||
```bash
|
||||
# Story 1 documentation and tooling work in parallel:
|
||||
Task: T009 README.md and docs/PROJECT_SUMMARY.md
|
||||
Task: T010 Agents.md, GEMINI.md, .github/copilot-instructions.md, and .github/agents/copilot-instructions.md
|
||||
```
|
||||
|
||||
## Parallel Example: User Story 2
|
||||
|
||||
```bash
|
||||
# Story 2 website app work in parallel:
|
||||
Task: T014 apps/website/src/layouts/BaseLayout.astro, apps/website/src/pages/index.astro, and apps/website/src/styles/global.css
|
||||
Task: T015 apps/website/public/favicon.svg and apps/website/public/robots.txt
|
||||
```
|
||||
|
||||
## Parallel Example: User Story 3
|
||||
|
||||
```bash
|
||||
# Story 3 stability work in parallel:
|
||||
Task: T017 apps/platform/tests/Feature/WorkspaceFoundation/PlatformWorkspaceCompatibilityTest.php
|
||||
Task: T019 scripts/platform-sail and README.md
|
||||
Task: T020 docs/HANDOVER.md and docs/PROJECT_SUMMARY.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Story 1 Only)
|
||||
|
||||
1. Complete Phase 1: Setup.
|
||||
2. Complete Phase 2: Foundational.
|
||||
3. Complete Phase 3: User Story 1.
|
||||
4. **STOP and VALIDATE**: Confirm the repo root now exposes one clear command model for platform, website, and parallel local development.
|
||||
|
||||
### Incremental Delivery
|
||||
|
||||
1. Finish Setup and Foundational to establish the shared workspace baseline.
|
||||
2. Deliver US1 to make the repo root the canonical entry path.
|
||||
3. Deliver US2 to make the website a real standalone public app.
|
||||
4. Deliver US3 to prove platform stability and multi-app coexistence.
|
||||
5. Finish Polish to remove stale assumptions and run the full smoke pack.
|
||||
|
||||
### Parallel Team Strategy
|
||||
|
||||
With multiple developers:
|
||||
|
||||
1. Complete Setup and Foundational together.
|
||||
2. After Foundational:
|
||||
- Developer A: US1 root scripts, docs, and tasks
|
||||
- Developer B: US2 website app structure and assets
|
||||
3. After US1 and US2 are stable:
|
||||
- Developer C: US3 platform stability validation and rollout notes
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Suggested MVP scope for this feature is **User Story 1** after Setup and Foundational are complete.
|
||||
- `[P]` tasks touch different files or can be validated independently.
|
||||
- Story labels map each implementation task back to the originating user story for traceability.
|
||||
- The website must remain outside Sail in this slice; the platform must remain Sail-first.
|
||||
- No shared package layer, shared design-token, UI, or content package, docs app, customer or auditor surface, public API or developer portal surface, CMS, blog, or content-engine expansion, TenantPilot domain feature change, or large CI/CD re-architecture should appear while executing these tasks.
|
||||
Loading…
Reference in New Issue
Block a user