11# GDS estate desired-configuration v1 contract
22
3- Status: implemented with controlled mutation enabled for managed NDDev sources.
3+ Status: implemented. The shipped example estate enables controlled mutation
4+ only for selectors and operation capabilities that explicitly allow it.
45
56## Source boundary
67
@@ -19,10 +20,9 @@ estate/owners/*.yaml
1920estate/selectors/*.yaml
2021```
2122
22- The current baseline declares four owners: the personal ` example-user ` account,
23- the ` example-org ` organization, the ` example-media ` organization, and
24- the ` example-guild ` organization (read-only member, no mutation
25- capability). Installation IDs remain logical; their actual GitHub App and
23+ The shipped example declares five owners: ` example-user ` , ` example-org ` ,
24+ ` example-media ` , ` example-guild ` (observe-only), and the publisher account
25+ ` NDDev-OpenNetwork ` . Installation IDs remain logical; their actual GitHub App and
2626provider installation IDs are bound only by a private device-local
2727` github-runtime ` document, or by the gh-CLI credential variant (ADR 0034).
2828Estate secret references are portable ` secret:gds/... ` identities; they do not
@@ -41,12 +41,12 @@ discovery.default_management_mode = observe-only
4141rollout.mutation_mode = pull-request
4242```
4343
44- The generic NDDev source selector assigns ` managed ` ; every other selector
45- remains ` observe-only ` . Managed does not authorize an automatic write: apply
44+ The ` organization-sources ` and ` opennetwork-sources ` selectors assign
45+ ` managed ` ; the other shipped selectors assign ` observe-only ` . Managed does not authorize an automatic write: apply
4646also requires an exact immutable plan, signed approval, one-shot enablement,
4747fresh compare-and-swap evidence, an operation-scoped mutation capability, a
4848private runtime, and the device mutation kill switch. Archive, fork, server,
49- guild, personal, and Example-Media selectors remain outside this rollout.
49+ guild, personal, and example-media selectors remain outside this rollout.
5050
5151## Discovery and classification
5252
@@ -76,32 +76,18 @@ retain their own priority. Organization and personal server portfolios
7676use distinct device workspace roots so their filesystem placement remains
7777injective even when owners contain repositories with the same name.
7878
79- Selector priority bands are conventional :
79+ The shipped selectors use these priority bands :
8080
8181- ` 100 ` — generic classification (sources, forks);
8282- ` 200 ` — specialized non-fork overrides (servers, named-prefix families);
83- - ` 300 ` — state overrides that outrank topology and name (archived).
84-
85- The ` archived ` state takes precedence over both fork topology and server name.
86- The estate ships a priority-` 300 ` archived selector for every owner whose
87- fall-through source portfolio would otherwise misclassify an archived
88- repository, so a provider-archived repository resolves to
89- ` portfolio:archived-projects ` regardless of whether it is a fork, a source, or
90- a ` server-* ` superproject:
91-
92- - ` personal-archived ` matches ` owner:example-user ` with ` archived: true ` ;
93- - ` organization-archived ` matches ` owner:nddev ` with ` archived: true ` .
94-
95- A higher band must be distinct from every overlapping selector's priority to
96- avoid the equal-priority ambiguity the compiler rejects. The
97- ` organization-archived ` selector is defense-in-depth: no NDDev repository is
98- archived on the provider today, but without it a future archived NDDev
99- repository would fall through to ` portfolio:organization-projects ` under
100- ` organization-sources ` instead of ` portfolio:archived-projects ` . The
101- ` example-media ` and ` example-guild ` owners do not yet declare an
102- archived selector; add one if an archived repository ever appears under those
103- owners and would otherwise be misclassified by ` example-media-sources ` ,
104- ` example-media-servers ` , or ` guild-sources ` .
83+
84+ There is no archived selector in the shipped example. The compiler preserves
85+ the provider's ` archived ` observation, but classification follows the matching
86+ selector. An estate that defines archival by ownership can assign its archive
87+ owner to ` portfolio:archived-projects ` regardless of the provider flag. An
88+ estate that instead wants provider-archived precedence must declare an
89+ appropriate higher-priority selector. Equal-priority overlapping matches are
90+ rejected by the compiler.
10591
10692## Monotonic policy fields
10793
0 commit comments