Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
## ADDED Requirements
### Requirement: Garage v2 image policy
The `@suaveplan/testing-integration-garage-s3` plugin SHALL pin to `dxflrs/garage:v2.0.0` (name + minor version). A follow-up operational change tracked at `docs/superpowers/specs/2026-04-25-test-suite-audit.md §5` will pin to `sha256:<digest>`.
#### Scenario: Image tag pinned
- **WHEN** the container factory is invoked without injection
- **THEN** the resulting container uses image `dxflrs/garage:v2.0.0`
### Requirement: Dual-port exposure
The fixture SHALL expose two TCP ports from the container: the S3 API port on container port `3900` and the admin port on container port `3902`. Both MUST be mapped to host ports and recorded in `config.s3Endpoint` and `config.adminEndpoint`.
#### Scenario: Both endpoints recorded
- **WHEN** the container has started
- **THEN** `config.s3Endpoint` and `config.adminEndpoint` are populated with reachable host URLs
### Requirement: Env-bridge contract
The plugin SHALL declare and forward exactly four environment variables: `GARAGE_S3_ENDPOINT`, `GARAGE_S3_ACCESS_KEY_ID`, `GARAGE_S3_SECRET_ACCESS_KEY`, `GARAGE_S3_BUCKET`. When ALL four are set on the parent process at construction time, the fixture MUST enter env-bridge passthrough mode.
#### Scenario: env() returns the full four-key set
- **WHEN** the fixture has started
- **THEN** `fixture.env()` returns a record with exactly the four declared keys
### Requirement: Seven-step initialisation sequence
In container mode `start()` SHALL execute the following sequence against the admin port, in order, before declaring the fixture healthy:
1. `status` — read cluster status to discover the node id
2. `layout assign` — assign capacity to the discovered node
3. `layout apply` — commit the layout version
4. `bucket create` — create the configured bucket
5. `key create` — create an access/secret key pair
6. `bucket allow` — grant the key full permissions on the bucket
7. `key info` — read back the key to confirm and capture the secret
Any step failure MUST abort the sequence and reject `start()` with a coded error naming the failing step.
#### Scenario: Successful seven-step init
- **WHEN** `start()` is invoked against a fresh container
- **THEN** all seven admin operations execute in the order above before `start()` resolves
#### Scenario: Layout-apply failure aborts
- **WHEN** the third step (`layout apply`) fails
- **THEN** `start()` rejects with `code === "INTEGRATION.GARAGE_S3.LAYOUT_APPLY_FAILED"` AND steps 4–7 are not attempted
### Requirement: Healthcheck contract — admin port
`isHealthy()` SHALL probe the admin port (3902) with an HTTP request and resolve `true` only when the admin endpoint responds. The S3 port (3900) alone is NOT sufficient evidence of health.
#### Scenario: Admin port is the source of truth
- **WHEN** the S3 port is open but the admin port has not yet started
- **THEN** `isHealthy()` resolves `false`
### Requirement: Configurable timeouts
The fixture options SHALL accept `healthIntervalMs?: number` and `healthTimeoutMs?: number` overrides forwarded to `HealthPoller`. Defaults follow `HealthPoller`'s defaults (500 ms / 120 s).
#### Scenario: Override applied
- **WHEN** the fixture is constructed with `{ healthTimeoutMs: 30000 }`
- **THEN** `HealthPoller` rejects after 30 s when the container never becomes healthy
### Requirement: Injectable factories
The fixture constructor SHALL accept optional `containerFactory`, `execFn`, and `fetchFn` parameters for the container, admin-CLI exec, and admin-port HTTP calls respectively. Defaults invoke testcontainers, the container's exec API, and the global `fetch`.
#### Scenario: Injected execFn drives the seven-step sequence
- **WHEN** `execFn` is replaced with a stub that records every command
- **THEN** the recorded commands match the seven-step order
### Requirement: Error-code prefix
Errors thrown from the plugin SHALL carry codes matching `^INTEGRATION\.GARAGE_S3\.[A-Z_]+$`. At minimum the package SHALL define: `START_FAILED`, `STOP_FAILED`, `STATUS_FAILED`, `LAYOUT_ASSIGN_FAILED`, `LAYOUT_APPLY_FAILED`, `BUCKET_CREATE_FAILED`, `KEY_CREATE_FAILED`, `BUCKET_ALLOW_FAILED`, `KEY_INFO_FAILED`.
#### Scenario: Each step has its own coded error
- **WHEN** `bucket create` fails
- **THEN** the rejection's `code === "INTEGRATION.GARAGE_S3.BUCKET_CREATE_FAILED"` AND `context.step === "bucket-create"`