Compare commits
1 Commits
f7fdf3930c
...
cursor/67d
| Author | SHA1 | Date | |
|---|---|---|---|
| 58ad990488 |
61
openspec/specs/container-runtime/spec.md
Normal file
61
openspec/specs/container-runtime/spec.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Container Runtime
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Provide a reproducible multi-stage Docker image with FrankenPHP serving the application, supporting web, queue, and scheduler processes (SPEC §15.1–15.4).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Production image uses multi-stage FrankenPHP build
|
||||||
|
|
||||||
|
The system SHALL provide a multi-stage Dockerfile that builds Composer dependencies, frontend assets, and a FrankenPHP runtime image serving `public/`.
|
||||||
|
|
||||||
|
#### Scenario: Image builds reproducibly in CI
|
||||||
|
|
||||||
|
- **WHEN** the `container` CI job builds the Docker image from a clean checkout
|
||||||
|
- **THEN** the build completes successfully and produces a runnable image
|
||||||
|
|
||||||
|
### Requirement: FrankenPHP runs in regular mode only
|
||||||
|
|
||||||
|
The system MUST NOT enable FrankenPHP worker mode in the MVP. The runtime SHALL use FrankenPHP in regular mode (ADR-006).
|
||||||
|
|
||||||
|
#### Scenario: Runtime configuration is regular mode
|
||||||
|
|
||||||
|
- **WHEN** the production image starts the web process
|
||||||
|
- **THEN** FrankenPHP serves requests in regular mode without worker persistence
|
||||||
|
|
||||||
|
### Requirement: Runtime image runs as non-root when supported
|
||||||
|
|
||||||
|
The system SHALL configure the production runtime to run as a non-root user when the base image supports it.
|
||||||
|
|
||||||
|
#### Scenario: Container process is non-root
|
||||||
|
|
||||||
|
- **WHEN** the web container is running in production configuration
|
||||||
|
- **THEN** the primary process MUST NOT run as root
|
||||||
|
|
||||||
|
### Requirement: Same image supports web queue and scheduler processes
|
||||||
|
|
||||||
|
The system SHALL use the same application image for web, queue worker, and scheduler processes with distinct commands (SPEC §15.2).
|
||||||
|
|
||||||
|
#### Scenario: Queue worker starts from application image
|
||||||
|
|
||||||
|
- **WHEN** the queue process is started with `php artisan queue:work`
|
||||||
|
- **THEN** it uses the same built image as the web process
|
||||||
|
|
||||||
|
### Requirement: Production image contains no secrets in layers
|
||||||
|
|
||||||
|
The system MUST NOT embed secrets, credentials, or private keys in Docker image layers.
|
||||||
|
|
||||||
|
#### Scenario: Image inspection finds no embedded secrets
|
||||||
|
|
||||||
|
- **WHEN** the image is built in CI
|
||||||
|
- **THEN** build arguments and layers MUST NOT contain production secrets or `.env` values
|
||||||
|
|
||||||
|
### Requirement: Container healthcheck validates application availability
|
||||||
|
|
||||||
|
The system SHALL define a container healthcheck that verifies application availability via the `/up` endpoint or equivalent boot check.
|
||||||
|
|
||||||
|
#### Scenario: Unhealthy container is detected
|
||||||
|
|
||||||
|
- **WHEN** the application inside the container fails to respond healthy on `/up`
|
||||||
|
- **THEN** the container healthcheck MUST report unhealthy status
|
||||||
34
openspec/specs/design-tokens/spec.md
Normal file
34
openspec/specs/design-tokens/spec.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Design Tokens
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Define centralized visual tokens for the public site layout and components, ensuring consistent styling and baseline accessibility (SPEC §6.3, §6.5).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Design tokens are centralized for the public site
|
||||||
|
|
||||||
|
The system SHALL define minimum design tokens in a single source consumed by the public site layout and components. Tokens MUST cover typography families, font scale, spacing, border radius, container width, background/text/border/accent/state colors, shadows, and transition duration/easing.
|
||||||
|
|
||||||
|
#### Scenario: Public layout uses shared tokens
|
||||||
|
|
||||||
|
- **WHEN** a public page is rendered
|
||||||
|
- **THEN** visual properties MUST be derived from the centralized token definitions rather than arbitrary inline values
|
||||||
|
|
||||||
|
### Requirement: Public site respects reduced motion preference
|
||||||
|
|
||||||
|
The system SHALL honor `prefers-reduced-motion` by disabling or minimizing non-essential animations and transitions on the public site.
|
||||||
|
|
||||||
|
#### Scenario: User prefers reduced motion
|
||||||
|
|
||||||
|
- **WHEN** a visitor has `prefers-reduced-motion: reduce` enabled
|
||||||
|
- **THEN** the public site MUST NOT play non-essential motion effects
|
||||||
|
|
||||||
|
### Requirement: Public site meets baseline accessibility contrast
|
||||||
|
|
||||||
|
The system SHALL use color combinations on the public site that meet WCAG AA contrast requirements for text and interactive elements defined in the token palette.
|
||||||
|
|
||||||
|
#### Scenario: Primary text is readable
|
||||||
|
|
||||||
|
- **WHEN** primary body text is rendered on its background color
|
||||||
|
- **THEN** the contrast ratio MUST meet WCAG AA minimums
|
||||||
30
openspec/specs/health-check/spec.md
Normal file
30
openspec/specs/health-check/spec.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Health Check
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Expose a public health endpoint for availability verification by load balancers, orchestrators, and container healthchecks (SPEC §5.1, §15.5).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Public health endpoint responds without authentication
|
||||||
|
|
||||||
|
The system SHALL expose `GET /up` as a public healthcheck endpoint that does not require authentication.
|
||||||
|
|
||||||
|
#### Scenario: Application is healthy
|
||||||
|
|
||||||
|
- **WHEN** a client sends `GET /up` while the application is running normally
|
||||||
|
- **THEN** the system responds with HTTP 200 in a timely manner
|
||||||
|
|
||||||
|
#### Scenario: Health endpoint exposes no secrets
|
||||||
|
|
||||||
|
- **WHEN** a client sends `GET /up`
|
||||||
|
- **THEN** the response MUST NOT include credentials, tokens, stack traces, or environment secrets
|
||||||
|
|
||||||
|
### Requirement: Health endpoint reflects application failure
|
||||||
|
|
||||||
|
The system SHALL return a failure status when the application cannot initialize properly.
|
||||||
|
|
||||||
|
#### Scenario: Application cannot boot
|
||||||
|
|
||||||
|
- **WHEN** the application fails to boot due to misconfiguration or missing dependencies
|
||||||
|
- **THEN** the health endpoint MUST NOT return HTTP 200
|
||||||
62
openspec/specs/internal-authentication/spec.md
Normal file
62
openspec/specs/internal-authentication/spec.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Internal Authentication
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Provide authenticated access to the internal Filament panel for admin and assistant users, with role-based authorization and secure account management (SPEC §3.4, ADM-01, §12.1–12.2).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Internal users authenticate via Filament panel
|
||||||
|
|
||||||
|
The system SHALL provide authenticated access to the internal panel at `/admin` using Laravel's session-based authentication integrated with Filament 5.
|
||||||
|
|
||||||
|
#### Scenario: Active admin logs in successfully
|
||||||
|
|
||||||
|
- **WHEN** an active user with role `admin` submits valid credentials on the login page
|
||||||
|
- **THEN** the system authenticates the user and redirects to the Filament dashboard
|
||||||
|
|
||||||
|
#### Scenario: Active assistant logs in successfully
|
||||||
|
|
||||||
|
- **WHEN** an active user with role `assistant` submits valid credentials on the login page
|
||||||
|
- **THEN** the system authenticates the user and redirects to the Filament dashboard
|
||||||
|
|
||||||
|
#### Scenario: Inactive user is denied panel access
|
||||||
|
|
||||||
|
- **WHEN** a user with `is_active` set to false submits valid credentials
|
||||||
|
- **THEN** the system MUST NOT grant access to the Filament panel
|
||||||
|
|
||||||
|
### Requirement: User roles are limited to admin and assistant
|
||||||
|
|
||||||
|
The system SHALL store user roles using the `UserRole` enum with exactly two cases: `admin` and `assistant`. The system MUST NOT implement a granular permission system in the MVP.
|
||||||
|
|
||||||
|
#### Scenario: User is created with a valid role
|
||||||
|
|
||||||
|
- **WHEN** an administrator creates a user with role `admin` or `assistant`
|
||||||
|
- **THEN** the role is persisted and enforced on subsequent authorization checks
|
||||||
|
|
||||||
|
### Requirement: Email addresses are unique per user
|
||||||
|
|
||||||
|
The system SHALL enforce a unique constraint on user email addresses.
|
||||||
|
|
||||||
|
#### Scenario: Duplicate email rejected
|
||||||
|
|
||||||
|
- **WHEN** a user is created or updated with an email already assigned to another user
|
||||||
|
- **THEN** the system MUST reject the operation with a validation error
|
||||||
|
|
||||||
|
### Requirement: Password reset is available for internal users
|
||||||
|
|
||||||
|
The system SHALL support secure password reset for internal users using Laravel's built-in reset flow.
|
||||||
|
|
||||||
|
#### Scenario: User requests password reset
|
||||||
|
|
||||||
|
- **WHEN** a user submits a registered email on the password reset form
|
||||||
|
- **THEN** the system sends a reset link without revealing whether the email exists
|
||||||
|
|
||||||
|
### Requirement: Only admin manages internal users
|
||||||
|
|
||||||
|
The system SHALL restrict user management (create, update, deactivate) to users with role `admin`. Users with role `assistant` MUST NOT manage other users.
|
||||||
|
|
||||||
|
#### Scenario: Assistant cannot access user management
|
||||||
|
|
||||||
|
- **WHEN** an authenticated assistant attempts to access user management in the panel
|
||||||
|
- **THEN** the system MUST deny access via authorization policy
|
||||||
48
openspec/specs/quality-gates/spec.md
Normal file
48
openspec/specs/quality-gates/spec.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Quality Gates
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Enforce standardized test scripts, architecture boundaries, and blocking CI jobs to maintain code quality across the project (SPEC §13.6, §13.9, §14.1–14.2).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement: Standardized Composer test scripts exist
|
||||||
|
|
||||||
|
The system SHALL expose Composer scripts equivalent to `test:unit`, `test:feature`, `test:browser`, `test`, and `quality` with the composition defined in SPEC §13.9.
|
||||||
|
|
||||||
|
#### Scenario: Developer runs full quality gate locally
|
||||||
|
|
||||||
|
- **WHEN** a developer runs `composer quality`
|
||||||
|
- **THEN** the command executes static analysis, audits, and the applicable test suites
|
||||||
|
|
||||||
|
### Requirement: Architecture tests enforce domain boundaries
|
||||||
|
|
||||||
|
The system SHALL include Pest architecture tests that verify `App\Domain` uses strict types and does not depend on `App\Filament` or `App\Livewire`.
|
||||||
|
|
||||||
|
#### Scenario: Domain layer violates boundary
|
||||||
|
|
||||||
|
- **WHEN** code in `App\Domain` imports from `App\Filament` or `App\Livewire`
|
||||||
|
- **THEN** the architecture test suite MUST fail
|
||||||
|
|
||||||
|
### Requirement: CI pipeline blocks merge on five jobs
|
||||||
|
|
||||||
|
The system SHALL run a CI pipeline with blocking jobs named `static`, `unit`, `feature`, `browser`, and `container` as defined in SPEC §14.1.
|
||||||
|
|
||||||
|
#### Scenario: Static analysis fails on pull request
|
||||||
|
|
||||||
|
- **WHEN** a pull request introduces a Pint, PHPStan/Larastan, or Composer audit failure
|
||||||
|
- **THEN** the `static` job MUST fail and block merge
|
||||||
|
|
||||||
|
#### Scenario: Feature tests use PostgreSQL
|
||||||
|
|
||||||
|
- **WHEN** the `feature` CI job runs integration tests
|
||||||
|
- **THEN** the job MUST use PostgreSQL and MUST NOT substitute SQLite
|
||||||
|
|
||||||
|
### Requirement: Browser tests run against FrankenPHP-served application
|
||||||
|
|
||||||
|
The system SHALL execute browser tests using Pest Browser/Playwright against an application served by FrankenPHP in CI.
|
||||||
|
|
||||||
|
#### Scenario: Browser job validates served application
|
||||||
|
|
||||||
|
- **WHEN** the `browser` CI job runs
|
||||||
|
- **THEN** tests execute against the built application artifact or equivalent production-like image
|
||||||
Reference in New Issue
Block a user