Adventure: π§ͺ Blind by Design β π‘ Intermediate#43
Conversation
fc2303b to
d8b9639
Compare
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
d8b9639 to
515140a
Compare
β¦only PR Per @KatharinaSick's first instinct on review β and on reflection the author agrees: when the placeholder stubs are reachable from the side-nav they create more confusion than they resolve. The stub files stay on disk so docs/index.md's links don't 404, but they're not surfaced in navigation. Intermediate and Expert come back into the nav in off-on-dev#43 and off-on-dev#44 once their content is real. Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
515140a to
4a8fca7
Compare
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
β¦inner-only PR The two stub level-docs and the matching index.md cards were carried in solely so docs/index.md links did not 404. With the nav already trimmed (per @KatharinaSick on PR off-on-dev#42), and now with the cards out of the landing page, the Beginner PR is genuinely scoped to a single level. Intermediate and Expert each add their own card + level doc as part of their respective PRs (off-on-dev#43 / off-on-dev#44). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
4a8fca7 to
890b011
Compare
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
890b011 to
3709227
Compare
β¦only PR Per @KatharinaSick's first instinct on review β and on reflection the author agrees: when the placeholder stubs are reachable from the side-nav they create more confusion than they resolve. The stub files stay on disk so docs/index.md's links don't 404, but they're not surfaced in navigation. Intermediate and Expert come back into the nav in off-on-dev#43 and off-on-dev#44 once their content is real. Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
β¦inner-only PR The two stub level-docs and the matching index.md cards were carried in solely so docs/index.md links did not 404. With the nav already trimmed (per @KatharinaSick on PR off-on-dev#42), and now with the cards out of the landing page, the Beginner PR is genuinely scoped to a single level. Intermediate and Expert each add their own card + level doc as part of their respective PRs (off-on-dev#43 / off-on-dev#44). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Layer the three OpenFeature evaluation-context tiers (global, transaction, invocation) onto the Spring Boot lab and register a custom audit Hook so the targeting in flags.json fires per cohort (species, country, dose) and every evaluation lands in the audit log. Replaces the placeholder intermediate.md stub with the full level doc, ships the Intermediate solution walkthrough, broken-state code, verify.sh, and devcontainer. Stacked on top of off-on-dev#42 (π’ Beginner). Review that one first. Part of off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
- rename 'π§ͺ The story (optional)' β 'πͺ The Backstory' - pin flagd image to v0.15.4 (was: ':latest') - devcontainer: forward only :8080 (was: 8080+8013+8014+8015+8016) - drop the published flagd ports β sidecar reaches the lab on the docker-internal network as flagd:8013 - drop the inline solutions/intermediate.md cross-link and the closing 'Spoiler ahead?' callout (solutions are unpublished pre-deadline) - replace 'Run the Verification Script' wording with the Adventure 03 template (verify.sh + Certificate of Completion) - verify.sh: lean on lib/scripts/http.sh test_http_endpoint for the reachability check Refs: PR off-on-dev#42 review by @KatharinaSick Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirror @KatharinaSick's Beginner pattern (605dabc): a thin Makefile for discoverability + remove the solution doc since solutions are not meant to be published before the challenge launch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirrors the structure Beginner adopted in PR off-on-dev#42 review (06789e7) β a discrete "Start the Lab" step before any forwarded-port click, so users who open the Ports tab early don't hit a 502. Renumbers downstream sub-steps (3a/b/c β 4a/b/c) and renames the post-fix run section to "Re-run the Lab with a Cohort" to disambiguate from the new step 2. Carries the same review feedback Katharina left on the Beginner level forward to the Intermediate level so the per-level shape stays consistent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3709227 to
fa2720c
Compare
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
KatharinaSick
left a comment
There was a problem hiding this comment.
I didn't play it yet but looks great! Left a couple of comments :)
| π Challenge directory: | ||
| $CHALLENGE_DIR | ||
|
|
||
| π§ͺ Sibling services already running (managed by devcontainer compose): |
There was a problem hiding this comment.
There are multiple ports mentioned here but only 8080 is forwarded in devcontainer.json. is that intended?
There was a problem hiding this comment.
As everything happens in teh terminal: do we even need to forward any port?
|
|
||
| The lab and a flagd sidecar run as siblings in the devcontainer's compose stack. The OpenFeature client uses `Resolver.RPC` to reach `flagd:8013`; flagd is the one watching `flags.json` and serving evaluations from it. The targeting rules live entirely inside `flags.json`; your job is to make sure the attributes the rules reference (`species`, `country`, `dose`) are populated on every evaluation. | ||
|
|
||
| ## π― Objective |
There was a problem hiding this comment.
I always try to keep the objective focused on outcomes not on how to get there. Further, there should be only a hand full (3-5). Would it be possible to change that? Or is it important for the challenge to have all the detail in here? If it's the latter, I'm good with it :)
| - **`targetingKey`** β a special slot on the eval context that flag implementations use as the bucketing key for fractional rollouts. The SDK exposes it via `ec.getTargetingKey()` rather than `ec.getValue("targetingKey")`; the `ImmutableContext(targetingKey, attributes)` constructor sets it explicitly. In real apps it's typically a stable user id β i.e. the canonical PII identifier you do **not** want flowing into audit logs. | ||
| - **`Hook`** β interceptor for flag evaluations. `before`/`after`/`error`/`finallyAfter` fire around every `client.getXxxDetails(...)`. `HookContext.getCtx()` exposes the **merged** context β that's what makes an audit trail useful instead of a "got here" log line. | ||
|
|
||
| ## π§ What You'll Learn |
There was a problem hiding this comment.
What's the difference of what you'll learn and concepts you'll touch?
| - In `afterCompletion`, clears the transaction context. Servlet threads are pooled β if you don't clear, the previous request's species or targetingKey leaks into whichever request lands on the thread next. | ||
| - In a static initialiser, registers a `ThreadLocalTransactionContextPropagator` once on the OpenFeature API. Without it the SDK has no way to carry per-request context across the call into the controller, and the transaction context silently stays empty. | ||
|
|
||
| > βΉοΈ The Intermediate `verify.sh` doesn't exercise the `?userId=` branch (no Intermediate flag uses `targetingKey`). If you skip that branch, Intermediate still passes β but the Expert level's variant-distribution panel will collapse to a single bucket. The wiring is forward-looking on purpose. |
There was a problem hiding this comment.
It woudl be great if intermediate would fail too if it's not solved
There was a problem hiding this comment.
That's also one of the reason I like outcome based objectives more. It doesn't matter how the user gets there but the otucome can be verified :)
- Rewrite Objective as 5 outcome-based bullets β drop the mechanism-heavy list; mechanism moves into the per-step instructions where it earns its place. - Drop the "Concepts you'll touch" section; its load-bearing content migrates inline: HandlerInterceptor Javadoc into 4a, three-context-layer precedence rule into 4b, Hook lifecycle into 4d. - Add an explicit step 4c "Pass the dose as invocation context from Trial" β the dose-passing was an objective bullet with no corresponding implementation step. - Drop targetingKey / ?userId= wiring from Intermediate. No Intermediate flag uses it, the verifier didn't exercise it, and the PII callout it motivated belongs in Expert (where eval context flows into OTel spans and the leak surface is real). Architecture diagram + lead paragraph + step 4a + step 4d trimmed accordingly. - Devcontainer: drop forwardPorts. Intermediate is API-only β every curl runs from inside the Codespace terminal, so host-side forwarding adds noise without value. The post-start banner stops claiming flagd ports are forwarded (they were never forwarded; the banner was lying). - verify.sh: sync OBJECTIVE block to the new outcome-based docs; tighten the AuditHook check to grep for the literal '[AUDIT]' format the docs specify (was matching 'AUDIT|Before hook|After hook', too lenient). Addresses Katharina's review comments on intermediate.md:51 (objective shape), :77 (Learn vs Concepts overlap), :165 (verifier exercises the objective), and the post-start.sh:14 port-hygiene comments. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirrors the Intermediate cleanup (8bcf885) on Expert, plus picks up the targetingKey + PII discipline that was deferred from Intermediate. - Rewrite Objective as 5 outcome-based bullets β drop the mechanism-heavy list, drop the parenthetical "verified: SpeciesInterceptor wires userId" note (now redundant: targetingKey lives at the implementation level here, not the objective level). - Drop the "Concepts you'll touch" section. Its load-bearing content migrates inline to the per-step instructions: TracerProvider vs MeterProvider gloss into 4a, TracesHook/MetricsHook gloss into 4b, the ContextSpanHook authoring guide into a new 4c, and the fractional + targetingKey explanation into 4d. - Add explicit step 4c "Author and register your own ContextSpanHook" β the ContextSpanHook was an objective bullet with no corresponding implementation step (analogous to the missing dose-passing step on Intermediate). - Move the PII allowlist callout to step 4c β Expert is where it earns its place, since eval context is about to flow onto OTel spans that ship to SIEM-grade backends. The Intermediate cross-link goes away; the discipline lives here standalone. - Lift "Start the Lab" out of step 1 into its own step 2 β mirrors the Intermediate / Beginner shape, so a player who clicks the Ports tab before reading further doesn't see a 502. - Format Deadline + Community thread sections as Coming Soon callouts, matching Intermediate. - Sync verify.sh OBJECTIVE block to the new outcome-based docs. Addresses Katharina's review themes carried over from off-on-dev#43 (objective shape, Concepts vs Learn overlap, verifier exercises objective). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
KatharinaSick
left a comment
There was a problem hiding this comment.
I removed 2 little cd commands from the docs that are not needed. apart from that it looks good - playing was fun :)
please sign your commits and we're good to merge
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirrors the Intermediate cleanup (8bcf885) on Expert, plus picks up the targetingKey + PII discipline that was deferred from Intermediate. - Rewrite Objective as 5 outcome-based bullets β drop the mechanism-heavy list, drop the parenthetical "verified: SpeciesInterceptor wires userId" note (now redundant: targetingKey lives at the implementation level here, not the objective level). - Drop the "Concepts you'll touch" section. Its load-bearing content migrates inline to the per-step instructions: TracerProvider vs MeterProvider gloss into 4a, TracesHook/MetricsHook gloss into 4b, the ContextSpanHook authoring guide into a new 4c, and the fractional + targetingKey explanation into 4d. - Add explicit step 4c "Author and register your own ContextSpanHook" β the ContextSpanHook was an objective bullet with no corresponding implementation step (analogous to the missing dose-passing step on Intermediate). - Move the PII allowlist callout to step 4c β Expert is where it earns its place, since eval context is about to flow onto OTel spans that ship to SIEM-grade backends. The Intermediate cross-link goes away; the discipline lives here standalone. - Lift "Start the Lab" out of step 1 into its own step 2 β mirrors the Intermediate / Beginner shape, so a player who clicks the Ports tab before reading further doesn't see a 502. - Format Deadline + Community thread sections as Coming Soon callouts, matching Intermediate. - Sync verify.sh OBJECTIVE block to the new outcome-based docs. Addresses Katharina's review themes carried over from off-on-dev#43 (objective shape, Concepts vs Learn overlap, verifier exercises objective). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire the OpenTelemetry meter provider, register the OpenFeature MetricsHook + TracesHook, author a ContextSpanHook that copies the merged evaluation context onto Tempo spans, then diagnose and roll back a misbehaving fractional rollout (vision_amplifier_v2) on the Grafana LGTM dashboard β no redeploy. Replaces the placeholder expert.md stub with the full level doc, ships the Expert solution walkthrough, broken-state code (including the dashboard JSON and k6 loadgen), verify.sh, and devcontainer. Stacked on top of off-on-dev#43 (π‘ Intermediate). Review off-on-dev#42 then off-on-dev#43 first. This is the last PR in the series, so it closes the tracking issue. Closes off-on-dev#41 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirrors the Intermediate cleanup (8bcf885) on Expert, plus picks up the targetingKey + PII discipline that was deferred from Intermediate. - Rewrite Objective as 5 outcome-based bullets β drop the mechanism-heavy list, drop the parenthetical "verified: SpeciesInterceptor wires userId" note (now redundant: targetingKey lives at the implementation level here, not the objective level). - Drop the "Concepts you'll touch" section. Its load-bearing content migrates inline to the per-step instructions: TracerProvider vs MeterProvider gloss into 4a, TracesHook/MetricsHook gloss into 4b, the ContextSpanHook authoring guide into a new 4c, and the fractional + targetingKey explanation into 4d. - Add explicit step 4c "Author and register your own ContextSpanHook" β the ContextSpanHook was an objective bullet with no corresponding implementation step (analogous to the missing dose-passing step on Intermediate). - Move the PII allowlist callout to step 4c β Expert is where it earns its place, since eval context is about to flow onto OTel spans that ship to SIEM-grade backends. The Intermediate cross-link goes away; the discipline lives here standalone. - Lift "Start the Lab" out of step 1 into its own step 2 β mirrors the Intermediate / Beginner shape, so a player who clicks the Ports tab before reading further doesn't see a 502. - Format Deadline + Community thread sections as Coming Soon callouts, matching Intermediate. - Sync verify.sh OBJECTIVE block to the new outcome-based docs. Addresses Katharina's review themes carried over from off-on-dev#43 (objective shape, Concepts vs Learn overlap, verifier exercises objective). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Summary
Outcome by cohort: layer the three OpenFeature evaluation-context tiers (global, transaction, invocation) onto the Spring Boot lab and register a custom audit
Hook, so the targeting inflags.jsonfires per cohort (species, country, dose) and every evaluation lands in the audit log.What this PR ships
adventures/planned/00-blind-by-design/docs/index.mdβ adds the π‘ Intermediate card to the Choose Your Level gridadventures/planned/00-blind-by-design/docs/intermediate.mdβ challenge docadventures/planned/00-blind-by-design/docs/solutions/intermediate.mdβ solution walkthrough (kept in repo, hidden frommkdocs.yamlnav until challenge launch)adventures/planned/00-blind-by-design/intermediate/β broken-state Spring Boot project +verify.sh+run-austria.sh/run-germany.sh.devcontainer/00-blind-by-design_02-intermediate/Stacking
This is PR 2 of 3, branched from
adventure/blind-by-design-beginner(#42). The diff currently includes Beginner's content because this PR is stacked on top of it. Review #42 first β once it merges intomain, the Intermediate-only delta will become apparent here automatically.The original full-state PR #40 is kept open for reference and will be closed once all three per-level PRs land.
Part of #41