feat(services): traefik routing overrides via allowlisted middleware labels (#64)

services.traefik_labels (jsonb) holds operator-defined Traefik
middlewares keyed 'middlewares.<name>.<type>[.<field>]', validated
against an allowlist at write time. edgeLabels (extracted from
createReplica) scopes each definition to the service router as
<router>-<name> and auto-attaches it to the router's middleware chain
after builtins. Router/service/provider-level keys are rejected.

Surfaces: create/update API fields, services create/update
--traefik-label (repeatable, key=value), MCP arg docs, OpenAPI +
regenerated types, service-page Access editor (Routing overrides
card + textarea).

Also marks three stale ROADMAP2 items shipped: notification producers
round-out, build-on-node (PR #60), mobile env/domains/scaling (PR #61).

Generated with [Devin](https://devin.ai)

Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomáš DvořákandDevin authored and GitHub committed 2026-10-09 23:47:25 +02:00
1 parent 4071ed2991
commit a4bb7ad559
14 files changed
+445 -63

No files matched your search

+2
View File
@@ -88,6 +88,7 @@ export type ServiceEntity = {
nodeName?: string;
spread?: boolean;
placementTags?: string[];
traefikLabels?: Record<string, string>;
publicUrl?: string;
};
@@ -702,6 +703,7 @@ function normalizeService(service: RawService): ServiceEntity | null {
nodeName: service.node_name,
spread: service.spread,
placementTags: service.placement_tags,
traefikLabels: service.traefik_labels,
publicUrl: service.public_url,
};
}