# API Route Modularization and v1 Freeze v1

## Decision

The current v1 API is a demo/internal-user continuity surface. It is frozen for new product work.

This is not a public backward-compatibility commitment. There are no external client commitments for the current demo API. After the v3 UI/API migration is complete and demo/internal users have moved to the replacement surfaces, the v1 routes should be removed instead of kept as a permanent parallel API.

Allowed v1 changes:

- real production/demo bug fixes,
- security fixes,
- continuity fixes for demo/internal users,
- low-risk observability or validation improvements that do not change product shape.

New product work should target:

- temporary `/api/v1/v3/*` read-model routes while the v3 UI is being migrated, or
- a domain-owned route module when the long-term resource path is clear.

## Current Route Layout

```text
cmd/api/routes.go
  shared server types, bootstrap/public route registration, legacy handlers

cmd/api/routes_core_api.go
  authenticated core `/api/v1` public contract route registration

cmd/api/routes_v3_readmodels.go
  temporary v3 read-model coordinator and legacy handlers not yet extracted

cmd/api/routes_v3_readmodels_*.go
  temporary v3 read-model route registration split by product domain
```

The BFF remains a single `cmd/api` binary. This split is an ownership and maintainability boundary, not a runtime deployment boundary.

## Target Route Layout

Future route files should follow the domain model:

```text
routes_auth.go
routes_account.go
routes_access_*.go
routes_billing.go
routes_payments.go
routes_apps_*.go
routes_storage.go
routes_network_*.go
routes_provisioning_allocations.go
routes_provisioning_nodes.go
routes_provisioning_maas.go
routes_bootstrap_nodes.go
routes_node_internal.go
routes_platform_*.go
routes_admin_ops.go
routes_admin_evidence.go
routes_admin_runbooks.go
```

Handlers may remain in shared files until each domain is actively migrated. The first hard boundary is route registration: new work should use the owning domain route module instead of adding to a catch-all registrar.

## v3 Isolation

Keep v3 routes separate until the whole production migration is complete. The `/api/v1/v3/*` prefix is a migration namespace for page-shaped read models and should not become the default naming model for permanent resources.

When a v3 read model stabilizes:

1. decide whether it remains page-shaped or graduates to a durable resource API,
2. move its OpenAPI ownership into the correct domain fragment,
3. move registration/handler code into the correct domain route file,
4. keep short-lived compatibility only if a frontend rollout requires it.

## v1 Removal Gate

Remove or move legacy continuity routes when all of these are true:

- production UI no longer calls the v1 route,
- demo/internal users have a documented replacement or are explicitly retired,
- smoke tests and release validation use v3/domain-owned replacement routes,
- no external backward-compatibility commitment has been introduced for the route,
- the owning domain signs off that no demo-critical flow still depends on the old path.

The target state is not `v1 + v3`; it is domain-owned production routes aligned with the v3 product model.

## CI Guard

`scripts/ci/route_structure_guard.sh` enforces the first boundary:

- authenticated core API registration lives in `routes_core_api.go`,
- v3 read-model registration lives in `routes_v3_readmodels.go` or domain-specific `routes_v3_readmodels_*.go` files,
- `/api/v1/v3/*` routes do not get registered in core API route files.
