Skip to content

Environment details: implement Containers, Cloud, and APIs component tabs#773

Open
hegsie wants to merge 22 commits into
mainfrom
claude/env-details-component-tabs-p7othg
Open

Environment details: implement Containers, Cloud, and APIs component tabs#773
hegsie wants to merge 22 commits into
mainfrom
claude/env-details-component-tabs-p7othg

Conversation

@hegsie

@hegsie hegsie commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the three placeholder sub-tabs under the environment details Components tab (Containers, Cloud, APIs) with fully working features, end to end:

  • Schema (deploy schema, dual-sourced SSDT + EF in the same commit): Container, CloudResource, ApiRegistration entity tables; Environment* join tables with composite primary keys (deliberately not copying EnvironmentServer's missing-PK defect); per-type audit tables mirroring DaemonAudit.
  • Persistence: sources with CRUD, ByEnvId reads, and behavioural attach/detach outcomes (EnvironmentAttachmentOutcome), honouring an explicit do-not-copy list of known ServersPersistentSource defects (null-guarded deletes, eager-loaded projections). Insert-only audit sources. Registered in both DI registries (API Lamar + Monitor).
  • API: three RefData* controllers with typed attach/detach endpoints (PUT/DELETE {id}/environments/{envId}) instead of extending the stringly-typed ChangeEnvComponent dispatcher. Authorization: creates require PowerUser/Admin; update/delete require environment-write on every mapped environment (PowerUser/Admin fallback for unattached items); attach/detach require write on the target environment; all failures are 403/404/409 — never 200-with-false. Every write lands an audit row (incl. Attach/Detach). Composite-PK races map to 409.
  • Deployment variables: VariableScopeOptionsResolver conditionally emits EnvironmentContainers/EnvironmentCloudResources/EnvironmentApiRegistrations plus per-tag ContainerNames_*/CloudResourceNames_*/ApiRegistrationNames_* name lists (shared, generalized tag-splitting; scalar-when-one/array-when-many and space→underscore semantics preserved). Environments with no attached components produce a byte-identical variable set to before — enforced by a characterization test written prior to the change.
  • Web UI: three real tabs (grid + attach dialog + create/edit dialog), self-fetching via the typed ByEnvId endpoints on activation, write controls gated on environment.UserEditable. Typed client extended via a minimal faithful splice (all pre-existing generated files byte-identical; see drift note below).

Tests

~130 new tests, all green; pre-existing failures verified as platform baselines:

  • Dorc.Core.Tests 149/149 (characterization baseline, resolver emission/quirks, model-build, JSON round-trip)
  • Dorc.Api.Tests +101 (sources incl. do-not-copy items, 3× controller suites covering every endpoint × privileged/unprivileged, DI resolution)
  • Dorc.Monitor.Tests +2 (DB-free registry/resolver resolution — a missed registration fails in CI, not at deploy time)
  • dorc-web 135/135 (per-type columns, gating both directions, form binding, cold-cache deep-link lifecycle regression)

Process

Developed under the repo's HLPS → IS → JIT-spec process with adversarial review gates on every document and step; all artifacts and gate logs are in docs/env-details-component-tabs/ (HLPS v5, IS v2, per-step SPECs, REVIEW-* triage logs, VERIFICATION-S-008.md). Review gates caught and fixed real defects along the way, including tabs rendering permanently empty on deep links and a delete race returning 200-with-false.

Rollout notes (see docs/env-details-component-tabs/RELEASE-NOTES.md)

  1. Deploy the Dorc.Database dacpac before the API/Monitor — the Monitor's resolver reads the new tables at deploy time.
  2. Check live Properties data for collisions with the six new reserved variable names/prefixes before rollout; fixed emissions override same-named user properties for environments with attached components.
  3. One open evidence item: a manual UI round-trip (create → attach → edit → detach → delete) in a deployed environment — this dev sandbox has no SQL Server, so verification here is test-level only.
  4. Discovered pre-existing drift: committed web client / committed swagger.json / running API had diverged independently (generator pin also wrong — corrected to 7.13.0). This PR splices in only its own six generated files; a dedicated client true-up change is recommended (SPEC-S-006-client-regeneration.md).

Tag capacity expansion (raising server/database tag limits past 250 chars) is deliberately not in this PR — it ships separately with carry-over review findings.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb


Generated by Claude Code

claude added 21 commits July 16, 2026 23:30
… capacity

Documents current state of the Components sub-tabs (Containers, Cloud, APIs
are placeholder stubs with no backend) and the layered 250/50-char limits on
server ApplicationTags and database ArrayName, as a kickoff prompt for the
HLPS -> IS -> JIT spec process.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Covers full-stack implementation of the Containers, Cloud and APIs
component sub-tabs plus consistent widening of server/database tag
limits, with an Unknowns Register gating the HLPS checkpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Applies all 23 triaged panel findings (see REVIEW-HLPS-round1.md):
authorization now follows the Daemons controller precedent, tabs
self-fetch instead of extending EnvironmentContentApiModel, join tables
get explicit composite PKs, do-not-copy defect list added, swagger
regeneration workflow resolved from dorc-web README. Tag capacity
expansion rescoped to a separate PR per user direction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Fixes the authorization-strictness wording contradiction, adds audit
tables to schema scope, generalizes the runnability unknown, corrects
the daemons precedent citations and unknown/risk bookkeeping. Round-2
triage recorded in REVIEW-HLPS-round2.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
All nine round-2 resolutions confirmed present; one bookkeeping nit in
the round-1 carry-over list fixed. HLPS awaits user checkpoint on
blocking unknowns U-1..U-4.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
… (v4)

User resolved U-1..U-4: schemas as proposed, many-to-many attach,
env-write authorization, and - against the CRUD-only recommendation -
deployment/variable-resolution integration in scope. New section 5.7
exposes the three types via VariableScopeOptionsResolver (collection
variables + per-tag name lists mirroring ServerNames_), pulls the
Monitor DI registry and Dorc.Core.Tests into scope, adds SC-6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Conditional variable emission decided (inert for environments without
new component types), SC-6 reworded to recorded-call-set equality,
deploy-time blast-radius and variable-namespace collision risks added,
per-tag prefix naming aligned to entity names. Delta triage in
REVIEW-HLPS-v4-delta.md; verification round approved all eleven fixes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Nine ordered steps: characterization-test pre-flight, SSDT schema, EF
mirror, sources + dual DI registration, API controllers with typed
attach/detach, resolver integration, client regen, UI tabs, final
verification sweep. Two parallel tracks after S-004.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Merges the SSDT and EF schema steps into one dual-source step per the
HLPS same-step constraint, adds the missing pre-flight dependency edge
to client regen, gives the R-5 name-collision check an owning step,
moves U-11's full-stack determination to pre-flight, corrects the step
index, and makes each verification intent checkable at its own step
boundary. Steps renumbered S-001..S-008; triage in REVIEW-IS-round1.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Two cosmetic fixes applied (S-004 heading aligned with index, R-3 gate
labelled in S-006). IS awaits user checkpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Freezes the exact SetPropertyValue call-set for a representative and a
minimal environment (SC-6 baseline; mutation-verified). Toolchain record
answers U-11: API serves swagger locally (client regen viable); full
stack and SSDT dacpac unavailable on this platform, fallbacks recorded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
SSDT (deploy schema): three entity tables with unique Name indexes,
three environment join tables with composite PKs, three audit tables
mirroring DaemonAudit. EF mirror lands in the same commit: models,
configurations, DbSets, Environment navigations, and offline model-build
tests verifying table mapping and composite join keys.

Also tightens the S-001 characterization baseline per its gate review:
External and multi-per-type database branches now frozen, nested value
assertions completed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
…tries

Three persistent sources (CRUD, ByEnvId, behavioural attach/detach via
EnvironmentAttachmentOutcome) honouring the do-not-copy list: null-
guarded deletes, eager-loaded projections. Insert-only audit sources
mirror DaemonAuditPersistentSource. DTOs pulled forward from S-004
(sources return ApiModels per repo convention; recorded in SPEC-S-003).
Registered in PersistentDataRegistry (API/Lamar) and Monitor's
PersistentSourcesRegistry with DB-free resolution tests on both.
EnvironmentsPersistentSource.DeleteEnvironment now clears the new
collections (S-002 gate finding - FK safety on dacpac databases).

29 new tests in Dorc.Api.Tests, 1 in Dorc.Monitor.Tests; existing
suites at baseline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
VariableScopeOptionsResolver gains the three component sources and
conditionally emits EnvironmentContainers/EnvironmentCloudResources/
EnvironmentApiRegistrations collection variables plus per-tag
ContainerNames_/CloudResourceNames_/ApiRegistrationNames_ name lists -
only when items are attached, so environments without components
produce exactly the pre-change variable set (SC-6). Tag splitting is
generalized from AddPropertiesForServerNamesByType into a shared helper
preserving the space-to-underscore and scalar-when-one/array-when-many
semantics; null/empty tags are now skipped instead of throwing (the old
inline code NRE'd a whole deployment on a null server tag).

Characterization tests: constructor wiring only, frozen call-set
assertions untouched. New Dorc.Core.Tests suite covers emission,
absence, quirks, and untagged items; Monitor-side DB-free resolution
test proves the resolver builds with its new dependency chain (R-6).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
…trations

Pattern-first: RefDataContainersController sets the shape - open reads
(GetAll/ById/ByEnvId), creates gated on PowerUser/Admin, update/delete
gated on environment-write across every mapped environment with
PowerUser/Admin fallback for unattached items, typed attach/detach
endpoints gated on the target environment, all failures 403/404/409
(never 200-with-false), audit rows on every write including
Attach/Detach, DbUpdateException from the composite-PK race mapped to
409. CloudResources and ApiRegistrations controllers are mechanical
replicas; 66 controller tests (22 x 3 parity suites).

Also applies S-003 gate findings: Monitor registry now registers the
three audit sources (spec parity) and the two attach-not-found tests
assert no SaveChanges.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Adds Detach_WithoutEnvWrite_Returns403 across all three suites (gate
HIGH), maps a delete whose item vanished between existence check and
delete to 404 instead of 200-with-false (gate MEDIUM), and replaces the
attach/detach switch defaults with explicit success cases plus a throw
on unexpected outcomes (gate LOW). Replicas and parity suites
regenerated from the pattern-setter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Fresh spec fragments for the 15 new endpoints and 3 schemas were
script-spliced into the committed swagger.json and the six generated
files copied from a clean generator run (7.13.0, matching the committed
client's VERSION; the openapitools.json pin said 6.6.0 and is
corrected). Full regeneration is impossible without repo-wide churn:
the committed client, committed spec, and running API have drifted
apart independently and a true refresh breaks the app build - recorded
in SPEC-S-006 as a follow-up maintenance task. All pre-existing
generated files remain byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Each tab self-fetches its items via the typed ByEnvId endpoint on
activation, renders a sortable grid with per-type columns and per-row
Edit/Detach actions, and offers Attach (combo over all items) and New
(create/edit form with per-field maxlengths) dialogs - all write
controls disabled when the environment is not user-editable. Containers
is the pattern-setter; Cloud and APIs are scripted replicas. The
attached grid is deliberately inline (single consumer) rather than
mirroring env-servers' separate component. 15 new component tests;
placeholder text is gone from the repo (SC-1).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Adds the VariableValue JSON round-trip tests deferred from the S-005
gate, the full-suite evidence record, SC checklist, release notes with
deploy-ordering and reserved-variable-name callouts, and the
consolidated step-gate log. S-006/S-007 gate verdict pending; statuses
finalize after it reports.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
PageEnvBase assigns environment (firing notifyEnvironmentReady
synchronously) before environmentId on the cold-cache path, so a deep
link or hard refresh on a component tab left the grid permanently
empty. The tabs now derive the id from environment.EnvironmentId.
Attach dialogs guard against the unset-envId window. Lifecycle
regression tests reproduce the exact base-class ordering with a stubbed
typed client.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
…LIVERED

S-006/S-007 gate closed after the cold-cache fix verification; HLPS and
IS marked delivered; final evidence counts recorded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Comment thread src/Dorc.Api.Tests/Controllers/RefDataContainersControllerTests.cs Fixed
Comment thread src/Dorc.Api/Controllers/RefDataApiRegistrationsController.cs Fixed
Comment thread src/Dorc.Api/Controllers/RefDataCloudResourcesController.cs Fixed
Comment thread src/Dorc.Api/Controllers/RefDataContainersController.cs Fixed
Comment thread src/Dorc.Core/VariableScopeOptionsResolver.cs Fixed
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

Test Results

492 tests  +114   492 ✅ +114   7s ⏱️ ±0s
  3 suites ±  0     0 💤 ±  0 
  3 files   ±  0     0 ❌ ±  0 

Results for commit f72847f. ± Comparison against base commit a537bdc.

♻️ This comment has been updated with latest results.

hegsie pushed a commit that referenced this pull request Jul 17, 2026
Adds Success Criteria and Constraints (dual-source same-step schema,
rollout ordering, client regen, dev-environment limits), corrects the
enforcement-layer statement (EF HasMaxLength is metadata - effective
limits are 1000/250 and EnsureCreated drift is already live), gives the
PR #773 dependency an executable fallback, registers the stored-proc
liveness and Contains-false-positive decisions, splits the chip-editor
and relabel questions. Triage in REVIEW-HLPS-round1.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
The three CheckWritePermissionForItem methods find the first
unauthorized environment via FirstOrDefault instead of an implicitly
filtering foreach (same first-failure semantics and message). The three
GetByEnvId_DelegatesToSource tests assert the action result type via
IsInstanceOfType and cast, removing the nullable-flow ambiguity of
as-cast plus separate null assert. AddPropertiesForNamesByTag uses
TryGetValue instead of ContainsKey plus indexer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThrVYPPi2eSj92hR44XYLb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Environment details: implement Containers, Cloud, and APIs component tabs

4 participants