“Real environments. Zero friction. Empowering everyone”powered by Orbital
The delivery backbone behind every WWSE enablement — provisioning live Kubernetes environments, running the CI fleet, and driving instructor-led workshops at scale.
Claude analyzes failed integration tests, determines whether the root cause is in the
repo or the shared framework, then creates a fix branch and opens a PR.
agent ready
Running Agents
Repository
Branch
Type
Started
Elapsed
Log
—
Started
Repository
Branch
Type
Status
Duration
Log
Loading…
Repository
Branch
Arch
Failed step
Status
Failed at
Duration
Log
Fix
Loading…
Repository
#
Title
Author
CI
Updated
Fix
Loading…
Repository
#
Title
Author
Labels
Updated
Fix
Loading…
⚙ Fleet capacityLoading fleet state…❄ FROZEN
Loading workers…
Queue Depths
Training tests (end-to-end learner flow via the Enablement App path)
Repository
Arch
Status
History
Duration
Finished
Loading nightly results…
Integration tests
Repository
Arch
Status
History
Duration
Finished
Loading nightly results…
Common failure patterns
Framework Tests
Test the framework itself: unit tests, cluster engines, app exposure, Dynatrace components
Loading suites…
Recent Framework Runs
Timestamp
Suite
Arch
Result
Duration
Log
—
A profile is a named set of training repos. Map profiles to domains and tenants in the Tenants tab.
Loading profiles…
New / edit profile
Preview — what does a tenant receive?
Delivery table
Domain defaults
Tenant overrides
Registered tenants, sorted by type. Registrant, name and plan come from the tenant registry; — means that tenant registered before we captured the field, or its OAuth client could not read it. A ● after a name means it was read from the account API rather than typed by the registrant.
Tenant
Registrant
Name
Type
Plan
Profile
Training sources Orbital delivers — WWSE Hands-On / Learning Bytes / SE Onboarding repos, and private repos for customer workshops. Adding a repo validates it on GitHub (with Orbital's token) before it's managed; reference it from a profile in the Profiles tab.
Add a training source
Managed training sources
Repo
Branch
Type
Delivery
Every workshop across every tenant. Click a row to edit or administer it. Creating workshops stays in the enablement app, where a trainer picks a training from their own tenant's catalogue.
—
Loading workshops…
All workshops
When
Title
Trainer
Tenant
State
Seats
Registrants
Only people on this list can schedule a workshop, and only they can turn on the tenant-wide solutions toggle. This is not the same as being an admin, and it grants nothing inside a workshop — authority there is workshop membership.
Add a trainer
Registered trainers
Email
Name
Added by
Added
Note
Loading trainers…
Account OAuth client bootstrap install only
Paste it once. Nothing is stored here. Orbital uses the OAuth client to deploy the app, writes it into your tenant's own settings, and then discards it — it is never written to Orbital's disk, database or logs. From that moment the app is self-sufficient: it mints its own per-learner tokens and updates itself, on any tenant in any account, with no credential of yours living on this server.
How to create the OAuth client
In your tenant's account: myaccount.dynatrace.com → Identity & access management → OAuth clients → New. Add every scope below — the install is refused if any is missing, because a partly-scoped client produces an app that installs and then fails at runtime.
All 15 required scopes — 13 environment, 2 account
Scope
Why it is needed
Environment
app-engine:apps:install
install and upgrade the app
app-engine:apps:run
activate the installed version
app-engine:apps:delete
uninstall — needed for the Undeploy button below
app-settings:objects:read
check whether this tenant already has its Orbital token, so the install can tell you whether the manual step below is still outstanding. Optional — without it that check reports “could not verify” instead of a definite answer.
settings:objects:read
read the outbound allowlist before changing it
settings:objects:write
enable training-telemetry forwarding, add the hosts below to the outbound allowlist if your tenant enforces one, and — the important one — store this client in your own tenant so the app can mint and self-update without Orbital keeping anything
environment-api:api-tokens:read
list and clean up the per-learner tokens the app minted
environment-api:api-tokens:write
mint each learner's environment token directly (classic dt0c01) — the primary path, immune to per-user IAM differences
environment-api:activegate-tokens:write
mint the ActiveGate token a Kubernetes lab environment needs
document:documents:read
read training content stored on the tenant
document:documents:write
import labs and images under one service identity — any admin can then manage them without creating duplicate copies
document:documents:delete
remove labs the tenant's profile no longer lists
document:documents:admin
manage content documents regardless of which admin imported them
Account
platform-token:tokens:write
mint per-user platform tokens where classic token creation has been retired (rolled out per environment)
platform-token:tokens:manage
revoke them when a session ends
Orbital checks the client against your tenant before installing anything and names any scope that is missing, so a wrong client costs you a message rather than a broken install. Want to verify first without installing anything? Run the tenant readiness check — same probes, nothing deployed. Note: scopes cannot be added to an existing client — if one is missing, create a new client.
After install, and the outbound allowlist
After install: nothing, if the client is complete
The install writes the client into your tenant's own Settings → Training Token Minting and the app takes it from there — per-learner tokens, and its own updates. The deploy result says stored when that worked; if it says anything else it also says which permission is missing, and you can paste the same client on that Settings page by hand.
Why the app must mint at all: creating classic API tokens is being retired per environment, so a tenant that mints them happily today can stop tomorrow while a sibling tenant in the same account carries on. A client with the two platform-token account permissions is what makes that transition a non-event.
Outbound allowlist (if your tenant enforces it)
These hosts are added to your app-function allowlist during install:
autonomous-enablements.whydevslovedynatrace.com
raw.githubusercontent.com, api.github.com
wwse.apps.dynatrace.com
Working… building & deploying the app. This can take a minute or two — please don't refresh or close this page.
Every deploy, upgrade, undeploy and preflight refusal, newest first. Filters apply to the rows already fetched — raise the row count to widen the window.
When
User
Tenant
Stage
Action
Result
Version
Via
Loading…
Attribution registry — who deployed where. One row per registered install; org members only.
Tenant
Name
Audience
Deployer
Identity
Account URN
Via
Version
First seen
Last deploy
Loading…
Shell
Help & Reference
Keyboard shortcuts
?
Open this help panel
Esc
Close any open modal
/
Focus log search (when log modal open)
W
Toggle line-wrap in log (when log modal open)
Sync CLI — commands not in the UI
Run from /home/ops/enablement-framework/codespaces-framework as ops user, or via the Synchronizer tab for the commands that are wired up.
Command
Description
sync push-update --framework-version X.Y.Z
Create version-bump PRs across the entire fleet
sync tag --framework-version X.Y.Z
Create combined version tags on all consumer repos
sync release
Create a GitHub Release for the current framework version
sync cleanup-branches
Delete merged branches (local + remote) across fleet
sync protect-main
Enable branch protection on main for all repos
sync checkout
Checkout main across all repos and show status
sync revert
Revert uncommitted local changes in repos
sync generate-registry
Regenerate the Hub HTML registry page
sync generate-json
Regenerate repos.json for the org GitHub Pages registry
sync migrate-mkdocs
Migrate mkdocs.yaml to INHERIT pattern across repos
sync bump-repo-version
Bump repo-level version component
sync list-pr --approve
Approve all passing framework-update PRs
sync list-pr --merge
Merge all passing framework-update PRs
API endpoints not exposed in the UI
Method + Path
Body / notes
POST /api/framework/trigger
{"suite":"k3d-apps","ref":"main","arch":"amd64"} — trigger specific framework test suite
POST /api/ghpages/trigger
{"repo":"dynatrace-wwse/X","branch":"main"} — deploy GitHub Pages for one repo
POST /api/ghpages/trigger-fleet
{"branch":"main"} — deploy GitHub Pages for all repos
POST /api/builds/rerun/{job_id}
Re-queue a completed job with the same parameters
POST /api/queue/clear
{"arch":"amd64"} or {"arch":"all"} — drain job queue
GET /api/queue
List all jobs currently waiting in both queues
POST /api/sync/prs/invalidate
Force-refresh the open-PR cache
POST /api/sync/issues/invalidate
Force-refresh the open-issues cache
Redis — direct queue operations
# Inspect queues
redis-cli -a $REDIS_PASS LLEN queue:test:amd64
redis-cli -a $REDIS_PASS LRANGE queue:test:amd64 0 -1
# Running jobs
redis-cli -a $REDIS_PASS KEYS "job:running:*"
# Workers
redis-cli -a $REDIS_PASS KEYS "worker:*"
redis-cli -a $REDIS_PASS HGETALL worker:worker-x86_64-amd002