Skip to content

feat(BA-6921): AppConfig fragment write REST v2 API (CRUD)#12928

Open
jopemachine wants to merge 7 commits into
mainfrom
feat/BA-6921-app-config-fragment-rest-v2
Open

feat(BA-6921): AppConfig fragment write REST v2 API (CRUD)#12928
jopemachine wants to merge 7 commits into
mainfrom
feat/BA-6921-app-config-fragment-rest-v2

Conversation

@jopemachine

@jopemachine jopemachine commented Jul 16, 2026

Copy link
Copy Markdown
Member

📚 Stacked PRs

Part of the AppConfigFragment / AppConfig stack under BEP-1052 (epic BA-5781). Merge in order (bottom-up):

  1. feat(BA-6552): add app_config_fragments DB model and Alembic migration #12306feat(BA-6552): app_config_fragments DB model and Alembic migration
  2. feat(BA-6553): add app_config_fragments repository layer #12307feat(BA-6553): repository layer
  3. refactor(BA-6619): consolidate AppConfigScopeType into common.data (single definition) #12403refactor(BA-6619): consolidate AppConfigScopeType into common.data
  4. refactor(BA-6620): ExistsQuerier ops primitive + AppConfigAllowList.exists #12405refactor(BA-6620): ExistsQuerier + AppConfigAllowList.exists
  5. feat(BA-6554): add app_config_fragment service layer #12358feat(BA-6554): AppConfigFragment service layer
  6. feat(BA-6702): move fragment rank to the allow list with scope defaults #12516feat(BA-6702): move fragment rank to the allow list with scope defaults
  7. feat(BA-6701): expose allow-list rank on the v2 API surface #12517feat(BA-6701): expose allow-list rank on the v2 API surface
  8. feat(BA-6704): cascade app config subtree deletion from the definition #12518feat(BA-6704): cascade app config subtree deletion from the definition
  9. feat(BA-6626): app_config_fragment bulk repository layer #12426feat(BA-6626): app_config_fragment bulk repository layer
  10. feat(BA-6618): app_config_fragment bulk CRUD service layer #12401feat(BA-6618): app_config_fragment bulk CRUD service layer
  11. feat(BA-6810): AppConfigFragment visible-fragments query (repository layer) #12706feat(BA-6810): AppConfigFragment visible-fragments query (repository layer)
  12. feat(BA-6859): bind AppConfig fragments to their RBAC scope on write (repository layer) #12826feat(BA-6859): bind fragments to their RBAC scope on write (repository layer)
  13. feat(BA-6872): seed APP_CONFIG_FRAGMENT permissions into the RBAC role fixture #12837fix(BA-6872): seed APP_CONFIG_FRAGMENT permissions into the RBAC role fixture
  14. chore(BA-6873): drop the dead APP_CONFIG RBAC entity type #12839chore(BA-6873): drop the dead APP_CONFIG RBAC entity type
  15. feat(BA-6555): AppConfig merge engine + resolve service (service layer) #12359feat(BA-6555): AppConfig merge engine + resolve service (service layer)
  16. refactor(BA-6948): store app_config_fragments.scope_id as a nullable UUID #12984feat(BA-6948): store app_config_fragments.scope_id as a nullable UUID
  17. 👉 feat(BA-6921): AppConfig fragment write REST v2 API (CRUD) #12928feat(BA-6921): AppConfig fragment write REST v2 API (CRUD) ← you are here
  18. feat(BA-6922): AppConfig fragment search REST v2 API (admin + scoped) #12930feat(BA-6922): AppConfig fragment search REST v2 API (admin + scoped)
  19. feat(BA-6556): merged AppConfig REST v2 read API #12377feat(BA-6556): merged AppConfig REST v2 read API

Fork at #12928: the fragment search (#12930) and the merged-read (#12377) both stack on #12928 and can merge in either order once it lands.

Summary

Raw app_config_fragment write surface as REST v2 — create / get / update / purge — split out of the original combined PR. Writes and single-fragment reads are open to any authenticated user and gated by RBAC at the processor (a user acts on their own user-scope, a domain admin on their domain's, a superadmin on any; public is superadmin-only).

What's included

  • DTOs (common/dto/manager/v2/app_config_fragment/): create / update / purge inputs, AppConfigFragmentNode, payloads.
  • REST v2 (api/rest/v2/app_config_fragment/): POST /, GET|PATCH|DELETE /{fragment_id} — all auth_required.
  • Adapter (api/adapters/app_config_fragment/adapter.py): dedicated AppConfigFragmentAdapter.
  • RBAC wiring: AppConfigFragmentProcessors now injects the scope / single-entity / bulk RBAC validators (previously ungated).

The search surface (admin + scoped) moved to #12930 (BA-6922); the merged read to #12377 (BA-6556) — both stack on this PR.


📚 Documentation preview 📚: https://sorna--12928.org.readthedocs.build/en/12928/


📚 Documentation preview 📚: https://sorna-ko--12928.org.readthedocs.build/ko/12928/


📚 Documentation preview 📚: https://sorna--12928.org.readthedocs.build/en/12928/


📚 Documentation preview 📚: https://sorna-ko--12928.org.readthedocs.build/ko/12928/


📚 Documentation preview 📚: https://sorna--12928.org.readthedocs.build/en/12928/


📚 Documentation preview 📚: https://sorna-ko--12928.org.readthedocs.build/ko/12928/

@github-actions github-actions Bot added size:XL 500~ LoC area:docs Documentations comp:manager Related to Manager component comp:common Related to Common component labels Jul 16, 2026
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 82b529a to 2b22425 Compare July 16, 2026 09:01
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch 2 times, most recently from bff6a0c to c6c1db3 Compare July 16, 2026 09:23
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from c6c1db3 to 53b60df Compare July 16, 2026 09:34
jopemachine added a commit that referenced this pull request Jul 16, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
@jopemachine jopemachine changed the title feat(BA-6921): AppConfig fragment REST v2 API (write + search) feat(BA-6921): AppConfig fragment write REST v2 API (CRUD) Jul 16, 2026
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 53b60df to 436d45c Compare July 16, 2026 09:51
jopemachine added a commit that referenced this pull request Jul 16, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
jopemachine added a commit that referenced this pull request Jul 16, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 436d45c to b180d8b Compare July 16, 2026 10:59
jopemachine added a commit that referenced this pull request Jul 16, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
Comment thread src/ai/backend/manager/services/app_config_fragment/processors.py
Comment thread src/ai/backend/manager/api/rest/v2/app_config_fragment/registry.py
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from b180d8b to cc8fa8a Compare July 16, 2026 11:06
Comment thread src/ai/backend/manager/api/rest/v2/app_config_fragment/registry.py
jopemachine added a commit that referenced this pull request Jul 16, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
@jopemachine
jopemachine force-pushed the feat/BA-6555-app-config-merge-engine branch from 5b75d9e to 10388d5 Compare July 16, 2026 11:10
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from cc8fa8a to 5fa07ce Compare July 16, 2026 11:10
jopemachine added a commit that referenced this pull request Jul 16, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
Comment thread src/ai/backend/manager/api/adapters/app_config_fragment/adapter.py Outdated
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 5fa07ce to 2133188 Compare July 16, 2026 11:30
@jopemachine
jopemachine force-pushed the feat/BA-6948-app-config-fragment-scope-id-uuid branch from df4fe1e to 69fcb45 Compare July 21, 2026 05:11
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 20f41dd to d89d49e Compare July 21, 2026 05:12
@jopemachine
jopemachine force-pushed the feat/BA-6948-app-config-fragment-scope-id-uuid branch from 69fcb45 to 7c50d93 Compare July 21, 2026 05:16
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch 2 times, most recently from 64f2d18 to 02c6786 Compare July 21, 2026 05:44
@jopemachine
jopemachine force-pushed the feat/BA-6948-app-config-fragment-scope-id-uuid branch from 49be602 to 1d41686 Compare July 21, 2026 05:51
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 02c6786 to 0aa5954 Compare July 21, 2026 05:52
@jopemachine
jopemachine force-pushed the feat/BA-6948-app-config-fragment-scope-id-uuid branch from 1d41686 to 9c62736 Compare July 21, 2026 06:00
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch 3 times, most recently from 8ea687e to f0c7832 Compare July 21, 2026 07:55
jopemachine added a commit that referenced this pull request Jul 21, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch 2 times, most recently from 1df2041 to 0b84b9a Compare July 21, 2026 09:22
jopemachine added a commit that referenced this pull request Jul 21, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
Base automatically changed from feat/BA-6948-app-config-fragment-scope-id-uuid to main July 21, 2026 10:02
jopemachine and others added 6 commits July 21, 2026 19:03
Raw app_config_fragment write surface as REST v2: create / get / update /
purge, backed by a dedicated AppConfigFragmentAdapter.

Writes and single-fragment reads are open to any authenticated user and
gated by RBAC at the processor (scope / single-entity / bulk validators):
a user acts on their own user-scope, a domain admin on their domain's, a
superadmin on any (public is superadmin-only). Wires the RBAC validators
into AppConfigFragmentProcessors (previously ungated).

Base of the split; the fragment search API and the merged-read (resolve)
API (#12377) stack on top and reuse this entity's AppConfigFragmentNode DTO.
Merging the path id into the body DTO via model_copy() bypassed validation and
declared a required body field that was always overwritten, so a mismatched id
in the body was silently ignored and the OpenAPI spec advertised a field the
handler discards. Pass the id as its own argument instead.

The bulk item still carries its own id and is split out as
AppConfigFragmentUpdateItem, leaving UpdateAppConfigFragmentInput as the
single-fragment body.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The scope_type/scope_id agreement is the one piece of real logic in these DTOs:
public must name no owner, domain and user must name one, and a blank id is as
unusable as a missing one. Enumerate the full scope enum on both the accepted
and the rejected side so a new scope variant cannot slip through untested.

Also pin the update body split — the single-fragment body carries no id, while
the bulk item does — and the min_length on both bulk batches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follows the column becoming UUID NULL in BA-6948: the request and response DTOs
take UUID | None, so a non-UUID scope_id is rejected at the boundary instead of
reaching a row no scope query can find. The adapter no longer maps public to an
empty-string sentinel in either direction — None is what the column stores.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Report a failed bulk item by the fragment id it targeted rather than its batch
  position. Every bulk item names its own fragment, so the id is what the caller
  can act on; an index makes them correlate the failure back by hand.
- Declare _adapter at class scope, per the class-field rule in the root
  AGENTS.md.
- Drop the FK detail from the config_name description.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The request body carries scope_id as a plain UUID, but the creator spec now takes
an AppConfigScopeIdentifier — only scope_type says whether that UUID is a domain
or a user. The adapter is the boundary that knows both, so it does the reading.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 0b84b9a to 0fef542 Compare July 21, 2026 10:04
jopemachine added a commit that referenced this pull request Jul 21, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 0fef542 to 3b5c071 Compare July 21, 2026 10:15
jopemachine added a commit that referenced this pull request Jul 21, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
BaseRequestModel only maps a pydantic ValidationError onto
BackendAISchemaValidationFailed inside model_validate, and every production
entry point — BodyParam, QueryParam, PathParam, headers — parses that way. The
raw ValidationError the direct constructor raises is therefore unreachable in
service, so accepting either exception let the tests pass on a rejection no
caller can observe. Reject through model_validate and assert the one error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jopemachine
jopemachine force-pushed the feat/BA-6921-app-config-fragment-rest-v2 branch from 3b5c071 to 80e715c Compare July 21, 2026 10:27
jopemachine added a commit that referenced this pull request Jul 21, 2026
Fragment search surface, split out of the write PR (BA-6921, #12928):
system-wide admin search (superadmin) and principal-scoped search (auth),
with the filter/order/scope DTOs and the filter/order query converters.

Stacks on BA-6921 and reuses its AppConfigFragmentNode DTO. The scoped
search is the REST surface of the visible-fragments query (BA-6810).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:docs Documentations comp:common Related to Common component comp:manager Related to Manager component require:db-migration Automatically set when alembic migrations are added or updated size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants