# Azaion.Annotations — Restrictions > Only constraints **evidenced in code, configs, or Dockerfiles** are listed. Inferred-but-unverified items are flagged. ## Hardware | ID | Restriction | Evidence | |----|-------------|----------| | HW-01 | Service binary is built for ARM64 only — no AMD64 image is produced. | `.woodpecker/build-arm.yml` (`platforms: linux/arm64`); `Dockerfile` `--arch=$BUILDARCH` driven by `BUILDPLATFORM=linux/arm64`. | | HW-02 | Local writable filesystem is required at `images_dir` / `videos_dir` / (planned) `deleted_dir`. | `Services/AnnotationService.cs` (`File.WriteAllBytesAsync`), `Services/PathResolver.cs`, `directory_settings` table. | | HW-03 | Memory pressure scales with the largest single image read into memory by `FailsafeProducer` (re-reads the image to put bytes on the wire). | `Services/FailsafeProducer.cs:138` neighborhood. | ## Software | ID | Restriction | Evidence | |----|-------------|----------| | SW-01 | .NET 10 SDK and runtime — no fallback. | `Dockerfile` `mcr.microsoft.com/dotnet/sdk:10.0`, `aspnet:10.0`. | | SW-02 | PostgreSQL backend; migrator emits `IF NOT EXISTS`, `ON CONFLICT`, `CREATE TYPE` — Postgres 13+ semantics expected. | `Database/DatabaseMigrator.cs`. | | SW-03 | RabbitMQ broker with the **streams plugin** enabled — service uses `RabbitMQ.Stream.Client`, not classic queues. | `Services/FailsafeProducer.cs`. | | SW-04 | Linq2DB ORM, MessagePack with the contractless resolver, gzip wire format. | `Services/FailsafeProducer.cs`. | | SW-05 | JWT verification is **ES256 over admin's JWKS** (`JWT_JWKS_URL`); `ValidAlgorithms` is pinned to `EcdsaSha256`. Annotations is verifier-only — admin is the sole token issuer for the suite. JWKS retrieval requires HTTPS. | `Auth/JwtExtensions.cs`. | ## Environment | ID | Restriction | Evidence | |----|-------------|----------| | ENV-01 | Required env vars (fail-fast at startup via `ConfigurationResolver`): `DATABASE_URL`, `JWT_ISSUER`, `JWT_AUDIENCE`, `JWT_JWKS_URL`. Optional with defaults: `RABBITMQ_HOST`, `RABBITMQ_STREAM_PORT`, `RABBITMQ_PRODUCER_USER`, `RABBITMQ_PRODUCER_PASS`. | `Program.cs`, `Infrastructure/ConfigurationResolver.cs`, `Services/FailsafeProducer.cs`. | | ENV-02 | Service listens on port `8080` HTTP, no TLS terminator inside the image. | `Dockerfile` `EXPOSE 8080`, `ASPNETCORE_URLS=http://+:8080`. | | ENV-03 | Build stamps `AZAION_REVISION` from CI; `Program.cs` echoes it on startup. | `Dockerfile` `ARG AZAION_REVISION`, `Program.cs`. | | ENV-04 | Image tag scheme is branch-driven: `${BRANCH}-arm`. No semver tags. | `.woodpecker/build-arm.yml`. | | ENV-05 | Swagger UI is mounted unconditionally — present in production builds (ADR-005). | `Program.cs`. | | ENV-06 | CORS is config-driven (`CorsConfig:AllowedOrigins` + opt-in `CorsConfig:AllowAnyOrigin`); `CorsConfigurationValidator.EnsureSafeForEnvironment` refuses to start in `Production` when the allow-list is empty and `AllowAnyOrigin` is not set. ADR-006 retired. | `Program.cs`, `Infrastructure/CorsConfigurationValidator.cs`. | | ENV-07 | Boot-time `DatabaseMigrator.MigrateAsync()` runs on startup — no separate migration step in the deploy pipeline (ADR-007). | `Program.cs`, `Database/DatabaseMigrator.cs`. | ## Operational | ID | Restriction | Evidence | |----|-------------|----------| | OP-01 | SSE state is per-instance — no broker fan-out — so horizontal scaling is bounded today. | `Services/AnnotationEventService.cs` (in-process `Channel<>`). | | OP-02 | Outbox drainer has no row-leasing — running multiple instances will double-publish until RB-09 deduplication contract is in place. | `Services/FailsafeProducer.cs`. | | OP-03 | No automated test suite in repo; CI does build-and-push only. | `_docs/02_document/00_discovery.md`, `.woodpecker/build-arm.yml`. | | OP-04 | No lint or formatter step in CI. | `.woodpecker/build-arm.yml`. | | OP-05 | Dockerfile `HEALTHCHECK` calls `/health`; HTTP 200 expected by orchestrator. | `Dockerfile`. | | OP-06 | The service must be the only writer of `annotations_queue_records` — the table is treated as a private outbox. | `Services/AnnotationService.cs`, `Services/FailsafeProducer.cs`. | | OP-07 | DB connection string format is the Java/Hikari `jdbc:postgresql://…` style; `Helpers/PostgreSqlConnectionStringHelper` parses it. | `Helpers/PostgreSqlConnectionStringHelper.cs`. | ## Cross-cutting (suite-level, evidence in `suite/_docs/01_annotations.md`) | ID | Restriction | |----|-------------| | SUITE-01 | The shared JWT secret family is cross-service; revoking it invalidates every service token. | | SUITE-02 | Wire enums for `AnnotationStatus`, `MediaType`, `QueueOperation` are duplicated across services and must move in lock-step (or a single contract has to be published). | | SUITE-03 | Stream consumers (admin worker, AI training) commit offsets independently — Annotations does not own retention semantics. |