## 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
145 lines
9.5 KiB
Markdown
145 lines
9.5 KiB
Markdown
# TenantPilot Workspace
|
||
|
||
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.
|
||
|
||
## 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
|
||
|
||
- Filament admin: `/admin` (seed user `test@example.com`, set password via factory or `artisan tinker`).
|
||
- Microsoft Graph (Intune) env vars:
|
||
- `GRAPH_TENANT_ID`
|
||
- `GRAPH_CLIENT_ID`
|
||
- `GRAPH_CLIENT_SECRET`
|
||
- `GRAPH_SCOPE` (default `https://graph.microsoft.com/.default`)
|
||
- Without these, the `NullGraphClient` runs in dry mode (no Graph calls).
|
||
- **Required API Permissions**: See [docs/PERMISSIONS.md](docs/PERMISSIONS.md) for complete list
|
||
- **Missing permissions?** Scope tags will show as "Unknown (ID: X)" - add `DeviceManagementRBAC.Read.All`
|
||
- Deployment (Dokploy, staging → production):
|
||
- Containerized deploy; ensure Postgres + Redis are provisioned (see `docker-compose.yml` for local baseline).
|
||
- Run application commands from `apps/platform`, including `php artisan filament:assets`.
|
||
- Run migrations on staging first, validate backup/restore flows, then promote to production.
|
||
- Ensure queue workers are running for jobs (e.g., policy sync) after deploy.
|
||
- Keep secrets/env in Dokploy, never in code.
|
||
|
||
## 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 expose the official root workspace commands, while MCP launchers remain platform-only and delegate through `./scripts/platform-sail`.
|
||
|
||
## Bulk operations (Feature 005)
|
||
|
||
- Bulk actions are available in Filament resource tables (Policies, Policy Versions, Backup Sets, Restore Runs).
|
||
- Destructive operations require type-to-confirm at higher thresholds (e.g. `DELETE`).
|
||
- Long-running bulk ops are queued; the bottom-right progress widget polls for active runs.
|
||
|
||
### Troubleshooting
|
||
|
||
- **Progress stuck on “Queued…”** usually means the queue worker is not running (or not processing the queue you expect).
|
||
- Prefer using the Sail/Docker worker (see `docker-compose.yml`) rather than starting an additional local `php artisan queue:work`.
|
||
- Check worker status/logs: `cd apps/platform && ./vendor/bin/sail ps` and `cd apps/platform && ./vendor/bin/sail logs -f queue`.
|
||
- **Exit code 137** for `queue:work` typically means the process was killed (often OOM). Increase Docker memory/limits or run the worker inside the container.
|
||
- **Moved app but old commands still fail** usually means the command is still being run from repo root. Switch to `cd apps/platform && ...` or use `./scripts/platform-sail ...` only for tooling that cannot set `cwd`.
|
||
|
||
## Rollback checklist
|
||
|
||
1. Revert the relocation commit or merge on your feature branch instead of hard-resetting shared history.
|
||
2. Preserve any local app env overrides before switching commits: `cp apps/platform/.env /tmp/tenantatlas.platform.env.backup` if needed.
|
||
3. Stop local containers and clean generated artifacts: `cd apps/platform && ./vendor/bin/sail down -v`, then remove `apps/platform/vendor`, `apps/platform/node_modules`, `apps/platform/public/build`, and `apps/platform/public/hot` if they need a clean rebuild.
|
||
4. After rollback, restore the matching env file for the restored topology and rerun the documented setup flow for that commit.
|
||
5. Notify owners of open feature branches that the topology changed so they can remap outstanding work before the next merge from `dev`.
|
||
|
||
## Deployment unknowns
|
||
|
||
- Dokploy build context for a repo-root compose file plus an app-root Laravel runtime still needs staging confirmation.
|
||
- Production web, queue, and scheduler working directories must be verified explicitly after the move; do not assume repo root and app root behave interchangeably.
|
||
- Any Dokploy volume mounts or storage persistence paths that previously targeted repo-root `storage/` must be reviewed against `apps/platform/storage/`.
|
||
|
||
### Configuration
|
||
|
||
- `TENANTPILOT_BULK_CHUNK_SIZE` (default `10`): job refresh/progress chunk size.
|
||
- `TENANTPILOT_BULK_POLL_INTERVAL_SECONDS` (default `3`): Livewire polling interval for the progress widget (clamped to 1–10s).
|
||
|
||
## Intune RBAC Onboarding Wizard
|
||
|
||
- Entry point: Tenant detail in Filament (`Setup Intune RBAC` in the ⋯ ActionGroup). Visible only for active tenants with `app_client_id`.
|
||
- Flow (synchronous, delegated):
|
||
1) Configure Role (default Policy/Profile Manager), Scope (global or scope group), Group mode (create default `TenantPilot-Intune-RBAC` or pick existing security-enabled group). Review planned changes.
|
||
2) Delegated admin login (short-lived token, **not** stored in DB/cache).
|
||
3) Execute: resolve service principal, ensure/validate security group, ensure membership, ensure/create/patch Intune role assignment; persists IDs on tenant for idempotency; no queue.
|
||
4) Post-verify: forces fresh token, runs canary reads (deviceConfigurations/deviceCompliancePolicies; CA canary only if feature enabled), updates health and warnings (scope-limited, CA disabled, manual assignment required).
|
||
- Safety/notes: least-privilege default, idempotent reruns, “already exists” treated as success. If service principal missing, run Admin consent first. Scope-limited setups may yield partial inventory/restore; warnings are surfaced in UI and health panel.
|
||
|
||
## Graph Contract Registry & Drift Guard
|
||
|
||
- Registry: `config/graph_contracts.php` defines per-type contracts (resource paths, allowed `$select`/`$expand`, @odata.type family, create/update methods, id field, hydration).
|
||
- Client behavior:
|
||
- Sanitizes `$select`/`$expand` to allowed fields; logs warnings on trim.
|
||
- Derived @odata.type values within the family are accepted for preview/restore routing.
|
||
- Capability fallback: on 400s related to select/expand, retries without those clauses and surfaces warnings.
|
||
- Drift check: `cd apps/platform && php artisan graph:contract:check [--tenant=]` runs lightweight probes against contract endpoints to detect capability/shape issues; useful in staging/CI (prod optional).
|
||
- If Graph returns capability errors, TenantPilot downgrades safely, records warnings/audit entries, and avoids breaking preview/restore flows.
|
||
|
||
## Policy Settings Display
|
||
|
||
- Policy detail pages render normalized settings instead of raw JSON:
|
||
- OMA-URI/custom policies → path/value table
|
||
- Settings Catalog → flattened key/value entries
|
||
- Standard objects → labeled key/value view with metadata filtered
|
||
- Version detail pages show both pretty-printed JSON and normalized settings.
|
||
- Warnings surface malformed snapshots or @odata.type mismatches before restore.
|
||
|
||
## Policy JSON Viewer (Feature 002)
|
||
|
||
- **Location**: Policy View pages (`/admin/policies/{record}`)
|
||
- **Capability**: Pretty-printed JSON snapshot viewer with copy-to-clipboard
|
||
- **Settings Catalog Enhancement**: Dual-view tabs (Settings table + JSON viewer) for Settings Catalog policies
|
||
- **Features**:
|
||
- Copy JSON to clipboard with success message
|
||
- Large payload detection (>500 KB) with warning badge and auto-collapse
|
||
- Dark mode support integrated with Filament design system
|
||
- Browser native search (Cmd+F / Ctrl+F) for finding specific keys or values
|
||
- 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
|