Skip to content

Signal-native page migrations + framework + async-job contract#5307

Draft
norman-abramovitz wants to merge 301 commits intodevelopfrom
feature/home-page-parallelization
Draft

Signal-native page migrations + framework + async-job contract#5307
norman-abramovitz wants to merge 301 commits intodevelopfrom
feature/home-page-parallelization

Conversation

@norman-abramovitz
Copy link
Copy Markdown
Contributor

@norman-abramovitz norman-abramovitz commented Apr 25, 2026

Summary

Post-Angular-21 work stream consolidating signal-native page migrations, new SignalList framework slots, and an end-to-end async-job contract for slow CF v3 operations. Dev iterations v5.0.0-dev.10 → dev.26.

What's in here

Signal-native infrastructure

  • EndpointDataService / OrgDataService / EndpointDataRegistry — per-endpoint and per-org signal stores with parallel fetch
  • EndpointDataShim — write-through bridge from Stratos-shape to NgRx
  • Stratos-shaped TypeScript DTOs for native Jetstream routes
  • Session-level endpoint concurrency config exposed to frontend

Page migrations to signal-native list

  • Endpoints, marketplace, services wall (multi-CNSI)
  • CF organizations tab, organization spaces tab
  • CF space routes/apps/service-instances/users tabs
  • CF users page
  • Plus: CF-level routes page (new)

SignalListConfig framework additions

  • headerActions slot for page-level actions (Manage Roles, Invite User…)
  • Compound maxVisible for cells with hundreds of segments
  • Per-row kebab action menu

App wall improvements

  • Favorite-star column, running/desired instances column
  • Text filter targets name/state/CF-Org-Space
  • Cross-tab navigation from summary cards
  • Compound CF/Org/Space cell with stacked links
  • App-stats refresh after scale to unstick Instances tab

Async-job contract (Jetstream)

  • New stratosjobs plugin with translator, tracker, types
  • References norman-abramovitz/fw-capi fork for Apps.Delete(*Job, error) until upstream lands

Bug fixes

  • CF org/space favorite stars leaking across CF endpoints sharing one CAPI — root cause was endpointDataService held in a plain field; orgs / spaces computeds tracked only the first endpoint's signal forever. Fix wraps the field in WritableSignal so the computeds re-track on CNSI swap. Affects cf-orgs-signal-config and cf-spaces-signal-config.
  • NG0955 track-by spam in signal-list.component.html — favorite/actions columns share an empty header, so tracking by col.header produced duplicate "" keys on every CD pass. Switched all six call sites to col.key. Console quieter, rendering noticeably faster.
  • Meta-card [favorite] race with [entityConfig] — converted favorite to a setter that records whether the parent bound it, and moved the entity-monitor fallback subscription to ngOnInit so the race no longer overwrites a parent-supplied favorite via the entity-stamped cfGuid.
  • Orgs page-size default 25 → 24 so the card-mode default lands in the card pageSizeOptions list (table-mode 25 was leaving the dropdown showing 6 while 25 cards rendered).
  • Connect-endpoint dialog stuck after failed connect; Previous now re-enabled with auto-unregister so the form can re-submit cleanly.
  • Empty endpoint authTypes default to UsernamePassword + None so plugin-package endpoints (metrics, autoscaler) render their Connect step instead of crashing on Object.keys(undefined).
  • Auth-type dropdown panel anchored to its trigger inside the register modal (Tailwind transform utility on modal content was creating a containing block and breaking position:fixed math).
  • Stepper now markForCheck'd after busy resets so retry works under OnPush + zoneless.
  • TailwindDialog panel uses opacity-only open animation (transform-based animation also created a containing block on every dialog).
  • CF SSH using process GUID not app GUID
  • App instances duplicate rows + button displacement
  • PostCSS nesting warning, deploy-step2 test crash
  • CNSI GUID missing from CF pagination cache keys

Dependency bumps

  • golang.org/x/crypto across three plugins (clears 6 moderates)
  • @stratosui/devkit to Angular 21 toolchain

Test plan

  • Full local gate (make check gate) green
  • Adepttech smoke: app wall, marketplace, services wall, routes, CF users, per-space tabs (apps, routes, service-instances, users)
  • App actions: scale, restart, restage, delete (async-job path)
  • Endpoint connect/disconnect flow incl. failed-connect recovery
  • Cross-endpoint favorite walk-through: navigate between three CF endpoints sharing one CAPI; org-stars must reflect each endpoint's own DB state, not whichever endpoint loaded first
  • E2E suite (local + adepttech)

Notes for review

  • Draft because the gate hasn't been run on the merged tip yet and there are followup items still active.
  • 200+ commits intentionally preserved — each migration is a discrete reviewable unit.
  • Commits follow the convention of listing dropped legacy features in the body.

…atched

- StOrg/StApp/StSpace gain cnsiGuid: string as a typed field matching
  the Stratos contract direction (Track 2 V3 migration).
- EndpointDataService and OrgDataService inject cnsiGuid into every
  resource from HTTP responses (Jetstream doesn't emit it yet).
- Shim dispatches build entity dictionaries keyed by cnsiGuid:guid
  composite, fixing the under-duplicate-URL collision that 2401443
  worked around. Apps are now dispatched through the shim (they were
  deliberately excluded under bare-guid keys because of the shared
  'applicationWall' pagination slot — composite keys resolve that).
- Specs updated: shim spec asserts composite keys and apps-through-shim;
  endpoint-data.service spec fixtures include cnsiGuid.
Per-entity byte count + entityType + cnsiGuid go to StratosDiagnostics
on every dispatch. Gives a first pass at effectiveness data: which
entities are biggest, which CFs contribute most to store weight.
entity-key-collision-avoided counter is deferred to Phase 10's
marquee integration test which exercises the N=3-4 duplicate-URL
scenario needed to trip it.
load() and loadDetails() increment service-call-count per invocation.
Cache-hit fires when a warm signal (recentApps populated or orgs
populated respectively) lets the call skip re-fetch work; cache-miss
fires otherwise. The registry wires diagnostics through to each
instance; the diagnostics param is optional on the service so tests
that construct without it stay working.
Plugin registered via plugin-config.yaml; extra_plugins.go regenerates
at build time from that source. Handler is admin-gated and only active
when DIAGNOSTICS_ENABLED env var is set — disabled responses return
404 (not 403) so production scanners can't detect feature availability.
SnapshotEnvelope mirrors the frontend's shape so one tooling consumer
reads both surfaces uniformly.
Middleware infrastructure: WrapClient(*http.Client, *Buffer) returns
a shallow copy whose RoundTripper tallies every request into the
buffer. Path GUIDs collapse to /:guid so aggregated counters don't
fragment into per-GUID noise.

Wiring into portalProxy.GetHttpClient is intentionally NOT in this
commit — that touches every CF call path and is best validated
against adepttech, not in unit tests. Phase 13 (deploy + validate)
will opt the CF HTTP client into the wrap when DIAGNOSTICS_ENABLED.
Phase 0.5's mock_server_test.go fixture alignment (cnsis columns
include meta_data AnyArg, /v3/info probe handler) incidentally made
this test pass. The TODO skip was stale — removing it recovers the
coverage that was dropped when the earlier cnsi_test.go fixtures
broke.
Composite entity keys eliminate the cross-endpoint GUID collision
that 2401443 worked around; the auto-scope + banner + refetch
plumbing is no longer necessary. Deleted:

- ApplicationWallComponent.countDuplicateUrlEndpoints + banner HTML
- CfAppConfigService.pickInitialCfGuid (restore "null when multiple
  CFs" default — the All view is now meaningful under composite keys)
- Post-ResetPagination re-dispatch in createCfOrSpaceMultipleFilterFn
- setMultiFilter-on-cf-change branch in list-pagination-controller

All associated specs deleted. Gate passes — test suite is the
acceptance proof that the underlying fix works.
Phase 9 deleted the banner along with the auto-scope workaround, but
the shared-URL fact itself is useful operator context — it signals
"you have N endpoints registered against the same foundation, probably
under different auth contexts." Composite keys make that situation
work correctly; the banner just surfaces the situation.

Wording updated to drop the "scoped to one connection's view" claim
(no longer true) and replace with "shown together — use the CF
filter to view a single endpoint."
Phase 5.2 added apps dispatch to the shim, reasoning that composite keys
made it safe. That's wrong: composite keys protect the entity dictionary
(still has all N × apps entries per CF) but the shared 'applicationWall'
pagination key is still last-write-wins. Each CF's shim.write() overwrote
the shared page with its own 52 IDs / totalResults=52, so the app wall
rendered 52 (not 104) apps and — when the page's composite IDs didn't
resolve under the app-wall's native fetch expectation — sometimes 0.

Yesterday's working shape (00a702a) explicitly did NOT dispatch apps
through the shim for exactly this reason. Phase 9 correctly deleted the
2401443 workaround, but Phase 5.2's apps-through-shim addition was a
*new* break, not an undo of anything. Restoring the orgs+spaces-only
shape. App wall's native fetch path handles multi-endpoint aggregation
correctly (and it relies on the composite entity dictionary Phase 3
provides for cross-endpoint isolation).

Also in this commit:
- manifest.yml: DIAGNOSTICS_ENABLED=true so the admin-gated diagnostics
  endpoint serves data on adepttech (test environment; prod default off).
- stratos-diagnostics.service: window.stratosDiagnostics now binds when
  isDevMode() OR localStorage.stratos.diagnostics === 'on'. Lets us
  inspect counts + samples from DevTools on adepttech prod builds
  without needing a dev build.
- Integration test: softened the collision-counter assertion to a
  "detection code runs without error" shape — the dispatch-spy harness
  can't observe real store state after mocked dispatches, so the counter
  will stay 0 in this test. Counter semantics are verified unit-side and
  will be re-verified live via window.stratosDiagnostics.
SEMVER_VERSION and GO_LDFLAGS were := (immediate) — captured package.json
at Make parse time. Chaining `make bump dev build release deploy cf`
let bump edit package.json at recipe time, but the already-captured
parse-time values flowed into stamp.frontend and the Go binary. Result:
build-info.ts stamped the pre-bump version even though package.json had
been updated.

Changed both to = (lazy). Preserves the interface distinction — VERSION
is user-settable input, SEMVER_VERSION is the derived internal canonical
— while letting consumers re-evaluate at recipe execution time.
Informational derivatives (SEMVER_MAJOR/MINOR/PATCH/PRERELEASE) stay :=
since they're only used by `dump version` which is a snapshot anyway.
Phase 9 deleted pickInitialCfGuid thinking it was purely a collision
workaround. It wasn't — it was also the only thing that gave
CfAppsDataSource a concrete endpointGuid to pass to GetAllApplications.
Without it, cfGuid=null on initial load and the backend fetch never
fires (GetAllApplications requires a specific endpointGuid; there's
no "all CFs" backend path). The app wall renders empty until the user
manually triggers a re-fetch via the in-app refresh button.

Restore a minimal version: pick the first connected CF as the initial
filter. Collision protection is no longer part of this function's
responsibility — composite keys (Phase 3) handle that. Users switch
between endpoints via the CF filter dropdown.

Note: apps are still slow to load because there's no shim pre-populate
for the applicationWall pagination key (Phase 5.2's apps-through-shim
was the wrong solution — it had last-write-wins overwrite semantics on
the shared key). Proper fix is a per-CF shim dispatch + aggregating
selector; deferred as a follow-up.
Add middleware.GzipWithConfig to the /pp API group with a skipper
that bypasses WebSocket upgrades (log-stream, firehose, cfapppush,
cfappssh) and MinLength=1024 to skip compression on small polling
responses where the CPU cost would outweigh the byte savings.

Add wireSizeMiddleware that buffers JSON responses and emits the
X-Stratos-Wire-Sizes header with raw_total / keys / values /
structural / resources byte breakdown. Active only when
DIAGNOSTICS_ENABLED. Feeds empirical measurement for whether
further format optimisation beyond gzip would help.

Track 2 page 1 — work unit 0 of the applications-wall migration.
See stratos KS docs/2026-04-20-track2-page1-appwall-plan.md.
Introduce the shared Go types for the Stratos-shape paging contract:
Href object-wrapper, PaginationMeta envelope with camelCase keys and
null-on-terminal link semantics, generic StratosPagedResponse[T] top-
level envelope, and StratosMeta / StratosError for the tristate /
multi-error _meta block.

BuildPaginationMeta constructs relative-path links from the incoming
request's own URL, preserving all non-page query params. No hardcoded
route templates; proxy-stripped prefixes just work.

Track 2 page 1 — work unit 1. No handler wiring or consumer yet;
that lands in WU 3.
Add memory (*int, MB), diskQuota (*int, MB), and orgGuid (*string)
to the Go StApp struct with json:",omitempty" tags; mirror with
optional memory, diskQuota on the TS StApp interface and move
orgGuid from required to optional. Pointer / optional shapes are
the tristate-discipline hint: absent on the wire when the handler
couldn't compose the field (e.g., /v3/processes fetch failed),
listed in _meta.unavailable for the affected rows.

Existing frontend consumers of StApp never read orgGuid (verified
via grep), so the required-to-optional change is safe. Memory and
diskQuota are new; no consumers yet — those land in WU 5 when the
app wall migrates to the primitive.

Track 2 page 1 — work unit 2. Handler wiring in WU 3.
Add ?return=summary branch to getNativeApps: parses Stratos-shape
paging (page, per_page), sort (order_by + direction, translated to
CAPI's minus-prefix form), and filter passthrough for every non-
reserved query param. Emits the StratosPagedResponse[StApp] envelope
with BuildPaginationMeta-built pagination links.

Uses existing toStApp so memory, diskQuota, and orgGuid are still
absent from rows — those land in WU 3b (/v3/processes composition)
and WU 3c (space-to-org resolution).

Backwards-compat paths (counts, recent, no-param) are untouched
and still return the legacy StAppsResponse shape; existing FWT-934
home-page card and any other no-param consumers keep working.

Track 2 page 1 — work unit 3a.
getNativeAppsSummary now fans out to /v3/processes?app_guids=...&
types=web after the app list comes back. The web Process per app
supplies memory_in_mb, disk_in_mb, and instances — populated into
the StApp.Memory, StApp.DiskQuota, and StApp.Instances fields.

When the processes fetch fails, the handler still returns HTTP 200
with the app-level fields intact. Each row carries a _meta.unavail-
able list noting the composition-dependent fields that couldn't be
populated; the envelope carries a _meta.errors entry with scope
"envelope", code PROCESSES_FETCH_FAILED, and the affected GUIDs +
field names. HTTP status reflects transport success; the payload
itself remains valid — the design distinction locked in Group 4.

Empty app list short-circuits the processes fetch.

Also:
- StApp gains _meta (*StratosMeta) for row-level tristate
- TS side adds matching StratosMeta / StratosError interfaces

Track 2 page 1 — work unit 3b. orgGuid composition in WU 3c.
Extend getNativeAppsSummary to batch-fetch the /v3/spaces referenced
by each app in the current page, then read relationships.organization
to populate StApp.OrgGUID. Unique space GUIDs dedupe across apps so
the lookup is one call per page regardless of app count.

Failure isolation: processes and spaces fetches are independent.
Either can fail without affecting the other or the app-level fields.
Each failure adds its own envelope _meta.errors entry (with its own
Affected field list) and each affected row gets those fields added
to its _meta.unavailable. Multi-error design (Group 4 decision)
surfaces all failures together.

The fw-capi library's ListResponse[T] doesn't expose CAPI's included
array, so ?include=space is skipped in favour of the separate batched
/v3/spaces fetch. If a future capi library version exposes Included,
this can collapse to one round-trip.

Track 2 page 1 — work unit 3c. Derived-field sort fallback in WU 3d.
CAPI V3's /v3/apps natively sorts on name, state, created_at, and
updated_at only — memory / diskQuota / instances live on processes
and aren't sortable server-side. For sort requests on those derived
fields, getNativeAppsSummary switches to a fetch-all + compose +
in-memory-sort + paginate path.

- isDerivedSortField dispatches; field name + direction returned
  without a minus-prefix helper for the sort routine
- fetchAllAppsWithFilters paginates /v3/apps across all CAPI pages
  with the request's filter set preserved, ignoring order_by + page
- sortStAppsByDerivedField sorts the composed slice stably; nil-
  valued rows (composition failure on that row) always sort to the
  end regardless of direction — unavailable data doesn't rank ahead
  of known data
- Page slice cut from the sorted in-memory set

Per-request buffer is bounded to one CF's matching app set — no
cross-CF buffering. Cross-CF merge is the frontend primitive's
concern in WU 4.

Track 2 page 1 — work unit 3d. WU 3 complete.
The bufferingResponseWriter embedded http.ResponseWriter without
overriding WriteHeader, so when a handler called ctx.JSON() the
status + headers flushed to the underlying writer before the
middleware's post-handler phase could set X-Stratos-Wire-Sizes.
Unit tests didn't catch this because they called handlers directly
without the middleware chain.

Override WriteHeader to capture the status code without forwarding;
add flushStatus() helper; call flushStatus() before writing the
buffered body or at overflow points. The final Header().Set() calls
in the middleware now land before the status line hits the wire.

Also add a WebSocket-upgrade skipper matching the gzip middleware so
log-stream / firehose / cfapppush / cfappssh don't have their
writers wrapped (hijack requires the raw writer).

Add five integration tests exercising the middleware in an Echo
chain (what the unit tests missed): header emitted on JSON responses,
absent when diagnostics off, non-JSON passes through, status code
preserved through buffering, WebSocket upgrade skipped.

Track 2 page 1 — WU 0 bug fix.
Capture elapsed server-side time from middleware entry to just
before flush; emit as an additional field in X-Stratos-Wire-Sizes.
Lets the eventual format-optimisation revisit (MessagePack vs
columnar tier vs stay-with-gzip) measure CPU cost alongside the
byte savings — bytes saved only matter if CPU time doesn't eat
the savings.

Example header post-change:
  X-Stratos-Wire-Sizes: raw_total=1910; keys=551; values=1221;
  structural=138; resources=5; duration_ms=45

Duration covers handler execution + JSON marshal + our tokenise
step + any sub-fetch composition. It is end-to-end server time,
not network transfer. Client-side parse time stays a DevTools
concern.

Track 2 page 1 — WU 0 extension.
Issue #2925 (historical P1): gzip on CF passthrough responses
corrupted Content-Type for Firefox. WU 0 re-enabled gzip on the
full /pp group, which potentially revives the regression on
/pp/v1/proxy/... paths. Add a shared Skipper predicate
(ppMiddlewareSkipper) used by both gzip and wire-size middleware
that bypasses:

  - WebSocket upgrades (already skipped; consolidated into the
    shared helper)
  - /pp/v1/proxy/* paths (new — fixes potential #2925 revival)

Passthrough paths aren't Stratos-shape so aren't the target of
wire-size instrumentation either; skipping also removes the
memory-pressure concern of buffering 200 KB+ CF proxy responses
before flushing.

Stratos-shape native endpoints (/pp/v1/cf/apps/{cnsi} and sibling
routes) keep gzip + wire-size — unchanged behavior.

Track 2 page 1 — WU 0 refinement.
uaaScopes and selectedScope are plain fields read by step 2's
template; the component runs OnPush. The async submit() awaits a
store.select before assigning them, and the assignments alone
don't trigger CD — step 2 could render with an empty scope
dropdown until something else marks the view dirty. Inject
ChangeDetectorRef and call markForCheck() at the end of submit.
Two signal-shape services that wrap the auth ngrx slice and a
localStorage-backed home prefs store. SessionService exposes
sessionData() / config() as signals for any page reading session
config. DashboardPreferencesService owns home-page prefs
(homeShowAllEndpoints, homeLayout) under stratos-home-prefs-{user},
hydrating from localStorage when the username becomes known.

Also exports SessionDataConfig from @stratosui/store so consumers
can type the config signal.
Removes the ngrx Store dependency from the home page and rewires the
internal data flow to signals + computed + effect.

- Router redirect: store.dispatch(new RouterNav) becomes
  inject(Router).navigate. Drops the RouterNav action wrapper.
- Endpoint bootstrap kick removed. auth.effects already dispatches
  GetAllEndpoints on every session verify, so the home-side dispatch
  was redundant.
- Session config (homeViewShowFavoritesOnly, endpointCardConcurrency)
  reads via SessionService instead of store.select(s => s.auth).
- Home prefs (homeShowAllEndpoints, homeLayout) read and write via
  DashboardPreferencesService instead of selectDashboardState +
  SetDashboardStateValueAction / SetHomeCardLayoutAction. The
  dashboard ngrx slice keys for these become dead.
- Internals: combineLatest / switchMap / pipe chain replaced with
  computed() signals and a single side-effect effect for show-mode
  persistence + noneAvailableMsg refresh. allFavorites,
  connectedEndpoints, haveRegistered, disablePersistenceFeatures
  bridged via toSignal at the boundary. Template @async pipes
  replaced with signal calls. allEndpointIds$ stays Observable
  because PageHeaderComponent still consumes it that way.

Existing dashboard ngrx slice persists for other consumers
(sidebar prefs, gravatar, timeoutSession, etc.). Users with prior
homeShowAllEndpoints / homeLayout in the DASHBOARD localStorage blob
see those values orphaned once - new prefs key takes over.

Spec: adds redirect + dispatch-guard tests for the home component;
adds full coverage for the two new services.
Drains capi.Stacks().List pages, maps each capi.Stack to a
Stratos-shape StStack DTO. Three TDD tests cover happy path,
empty result (resources:[] not null), and pagination drain.
Replaces CfStacksDataSource + CfStacksListConfigService + the legacy
CfStacksCardComponent with a per-CNSI CfStacksSignalConfigService,
CnsiStacksSource, and a SignalListComponent-driven page. Loads
through the native v3 handler and drops the ngrx pagination plumbing.
Drains capi.Buildpacks().List pages, maps each capi.Buildpack to a
Stratos-shape StBuildpack DTO. Coerces nullable Filename/Stack to
empty strings so the wire shape stays flat. Three TDD tests cover
happy path (READY + AWAITING_UPLOAD rows), empty result (resources:[]
not null), and pagination drain.
Replaces CfBuildpacksDataSource + CfBuildpacksListConfigService + the
legacy CfBuildpackCardComponent with a per-CNSI
CfBuildpacksSignalConfigService, CnsiBuildpacksSource, and a
SignalListComponent-driven page. Adds Position/Stack/Filename/Enabled/
Locked columns and drops the ngrx pagination plumbing.
Drains capi.SecurityGroups().List pages, maps each capi.SecurityGroup
to a Stratos-shape StSecurityGroup DTO. Reduces the rule array and
running/staging space relationships to counts so the list shape stays
flat; the future detail screen will own the full rule table. Three TDD
tests cover happy path (mixed globally-enabled + space binds), empty
result, and pagination drain.
…ty_groups

Replaces CfSecurityGroupsDataSource + CfSecurityGroupsListConfigService
+ the legacy CfSecurityGroupsCardComponent with a per-CNSI
CfSecurityGroupsSignalConfigService, CnsiSecurityGroupsSource, and a
SignalListComponent-driven page. Adds Rules / Global Running / Global
Staging / Running Spaces / Staging Spaces columns and drops the ngrx
pagination plumbing.
Drains capi.FeatureFlags().List pages, maps each capi.FeatureFlag to
a Stratos-shape StFeatureFlag DTO. Unlike most resources, feature
flags have no GUID — name is the identity — and no created_at; only
updated_at is tracked, and it is nullable along with custom_error_message.
Both nullables are coerced to empty strings server-side. Three TDD
tests cover happy path (enabled + disabled with error message), empty
result, and pagination drain.
…flags

Replaces CfFeatureFlagsDataSource + CfFeatureFlagsListConfigService +
the legacy table-cell-feature-flag-state and -description cell
components with a per-CNSI CfFeatureFlagsSignalConfigService,
CnsiFeatureFlagsSource, and a SignalListComponent-driven page.
Columns: Name / Enabled / Custom Error Message / Updated. Drops the
ngrx pagination plumbing.
Drains capi.OrganizationQuotas().List and capi.SpaceQuotas().List
respectively, mapping each capi quota onto a flat StOrgQuota or
StSpaceQuota DTO. v3 nests limits under Apps/Services/Routes/Domains
with nullable *int values; the handlers flatten that to top-level int
fields and coerce nil → -1 ("Unlimited") so the wire shape stays flat
ints and the frontend renders without null-guarding every cell.

Six TDD tests across the two suites cover happy path with mixed
limited/unlimited rows, empty result, and pagination drain.
The constant lived inside CfQuotasListConfigService — that file is
deleted as part of the signal-native quota migration. The legacy
add/edit quota wizards still consume the token to route back to the
list after save, so the constant now lives next to the wizards in
features/cf/quota-definition-base/quota-route-tokens.ts.
Replaces CfQuotasDataSource + CfQuotasListConfigService and
CfSpaceQuotasDataSource + CfSpaceQuotasListConfigService (and the
table-cell-quota cell component) with two signal-config services
(CfOrgQuotasSignalConfigService + CfSpaceQuotasSignalConfigService),
two CnsiEntitySource implementations, and two SignalListComponent-
driven page rewrites. Both pages render -1 limits as "Unlimited".

The space-quotas service exposes a basePredicate signal so the
org-page tab can restrict its foundation-wide list to the active org;
the foundation-wide cf-quotas page and the org-scoped tab share the
same backend handler with different filter shapes.

Drops the ngrx pagination plumbing and the legacy SCSS files that
went with the old card-mode renderers.
Adds [trace capi] and [trace handler] log lines at every cfClient.X.List()
call site in listAllOrgs, listAllSpaces, and getNativeSpaces (counts +
paginated paths) so a future 504 can be attributed to a specific page,
filter shape, or to gorouter cutting us off mid-handler. Also adds a
?per_page&page passthrough branch to getNativeSpaces — single CAPI call
returning a Stratos-shape paged envelope. Legacy callers without those
params keep their existing full-drain wire shape.
Adds two service-plan verticals on the Jetstream V3 native surface:

- Reads: GET list with StratosPagedResponse[StServicePlan], ?guids
  filter for batch lookup, ?return=counts fast path, single-resource
  GET /:planGuid for detail.
- Visibility: GET/POST/PATCH/DELETE on /:planGuid/visibility with
  one Echo handler dispatching POST→ApplyVisibility (replace) and
  PATCH→UpdateVisibility (merge). Names are inverted relative to
  CAPI HTTP semantics — documented inline.

Both verticals follow the wire-contract principles forced by the
spaces-504 incident: bounded pagination, single-resource endpoints,
guid-batch as a first-class branch, no implicit auto-drain.
Bounded list with ?guids batch + ?return=counts fast path, plus a
single-resource GET /:brokerGuid for detail. Mirrors the wire-contract
baseline established by service_plans: one CAPI call per request, no
auto-drain, guid-batch as a first-class branch.

Auth credentials are not surfaced on the read shape — those land with
the broker write vertical when it follows.
Bounded list with ?guids batch + ?return=counts fast path, plus a
single-resource GET /:domainGuid for detail. V3 unifies V2's split
shared/private domain endpoints into one resource — Stratos shape
flattens relationships into owningOrgGuid (empty = shared) and
sharedOrgGuids, surfaces internal + supportedProtocols + router
group guid as flat fields.
POST /pp/v1/cf/user_provided_service_instances/:cnsi creates via the
unified v3 /v3/service_instances with type=user-provided; PATCH
/:siGuid updates. Both are sync — no async-job dance — so the SDK
returns the resource directly via its interface{} return.

Surfaces syslogDrainUrl + routeServiceUrl on StServiceInstance as
omitempty fields, populated by the existing read pipeline as well.
Type discriminator is sent on create only; v3 forbids changing it
on update.
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.

1 participant