Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
180 commits
Select commit Hold shift + click to select a range
eb781fc
fix(csrf): re-authenticate on a real 401 in a stale session (#2239)
jung-thomas Sep 11, 2026
7698477
Merge pull request #2241 from sap-tutorials/worktree-fix-2239-stale-s…
jung-thomas Sep 11, 2026
2f94db8
feat(md): absolutize image URLs in served tutorial markdown (#2235)
jung-thomas Sep 11, 2026
18e54f5
Merge pull request #2242 from sap-tutorials/worktree-2235-absolutize-…
jung-thomas Sep 11, 2026
8d638ba
feat(devtoberfest): show Session Survey link in schedule detail panel…
jung-thomas Sep 11, 2026
42dc1fe
Merge pull request #2243 from sap-tutorials/feat/survey-link-consume
jung-thomas Sep 11, 2026
245ba5f
feat(mcp): expose per-step markdown via get_tutorial_step with format…
jung-thomas Sep 11, 2026
23c4b89
fix(mcp): mark RepoCatalog slug lookup as caller-canonicalized (#2244)
jung-thomas Sep 11, 2026
5947fca
docs(2245): design spec for signed provenance & freshness attestation
jung-thomas Sep 11, 2026
a23b2cf
docs(#2247): design spec for HCQL re-land on CAP 10.1.0
jung-thomas Sep 11, 2026
029bd1c
docs(2245): resolve open questions to approved defaults
jung-thomas Sep 11, 2026
357e5fa
docs(#2247): fold package.json-wide dep update into HCQL re-land spec
jung-thomas Sep 11, 2026
2273bc2
feat(content): serve markdown via Accept negotiation on primary tutor…
jung-thomas Sep 11, 2026
74d0b5e
feat(search): public anonymous semantic_search over content corpus (#…
jung-thomas Sep 11, 2026
5e5931a
docs(2245): implementation plan for signed provenance envelope
jung-thomas Sep 11, 2026
fc464b8
build(cds): regenerate csn.json snapshot for semanticSearchEnabled (#…
jung-thomas Sep 11, 2026
c949545
Merge pull request #2248 from sap-tutorials/worktree-issue-2244-mcp-m…
jung-thomas Sep 11, 2026
919bce3
Merge pull request #2252 from sap-tutorials/worktree-accept-markdown-…
jung-thomas Sep 11, 2026
274295f
feat(2245): register PROVENANCE_ENVELOPE_ENABLED db feature flag
jung-thomas Sep 11, 2026
0120c87
Merge remote-tracking branch 'origin/DEV' into worktree-semantic-sear…
jung-thomas Sep 11, 2026
e0f1c5b
Merge pull request #2253 from sap-tutorials/worktree-semantic-search-…
jung-thomas Sep 11, 2026
4db491c
docs(#2247): implementation plan for HCQL re-land
jung-thomas Sep 11, 2026
f4fd9f7
feat(2245): Ed25519 provenance key loader + JWKS export
jung-thomas Sep 11, 2026
f719534
feat(2245): freshness confidence derivation
jung-thomas Sep 11, 2026
d17d1a7
feat(ai): add navigable /sitemap.md site map
jung-thomas Sep 11, 2026
b8fd27f
Merge pull request #2254 from sap-tutorials/sitemap-md
jung-thomas Sep 11, 2026
6a23c3b
fix(ord): bump @cap-js/ord to ^1.9.3 so MCP surfaces are cataloged (#…
jung-thomas Sep 11, 2026
223af3e
feat(2245): persist per-slug sourceCommit through publish append
jung-thomas Sep 11, 2026
f4e9c9a
feat(2245): signed provenance envelope builder + cache
jung-thomas Sep 11, 2026
4bf1589
chore(#2247): Phase A — bump CAP ecosystem to cds 10.1
jung-thomas Sep 11, 2026
ada8ae5
feat(2245): serve-time provenance input loader
jung-thomas Sep 11, 2026
e1472f4
fix(2245): select latest FreshnessReport by runAt desc, scope medium-…
jung-thomas Sep 11, 2026
7d4f079
fixup(#2247): cap cds-caching at 2.1.0 (within current major)
jung-thomas Sep 11, 2026
4dcbf44
feat(2245): provenance JWS endpoint + JWKS route
jung-thomas Sep 11, 2026
0a2b84c
feat(2245): advisory freshness/provenance headers on tutorial serve
jung-thomas Sep 11, 2026
59ae9dc
feat(2245): thread source commit SHA through publish pipeline
jung-thomas Sep 11, 2026
6c1105f
docs(2245): signed provenance envelope endpoints, flag, key handling
jung-thomas Sep 11, 2026
aad0d96
fix(2245): re-gate cache-hit advisory headers on flag; doc corrections
jung-thomas Sep 11, 2026
bb05d04
chore(#2247): Phase B — within-major refresh of non-CAP deps
jung-thomas Sep 11, 2026
7f3a9b9
feat(#2247): enable HCQL on AdminService via /hcql/admin
jung-thomas Sep 11, 2026
c51776c
Merge pull request #2255 from sap-tutorials/fix-2249-ord-mcp
jung-thomas Sep 11, 2026
5756f4c
feat(#2247): enable HCQL on author/analytics/exports/consolidation
jung-thomas Sep 11, 2026
af1e3ce
feat(#2247): approuter routes for /hcql/* (XSUAA, JWT-forwarded)
jung-thomas Sep 11, 2026
fcc3e87
Merge remote-tracking branch 'origin/DEV' into worktree-provenance-en…
jung-thomas Sep 11, 2026
c79dd2b
docs(#2247): HCQL distinct paths, authenticated-only, 10.1.0 DoS-fixed
jung-thomas Sep 11, 2026
2c0f38b
docs(2245): design spec for assert blocks (parse + persist)
jung-thomas Sep 11, 2026
2e5b256
fix(2245): satisfy static guards — slug-canonical markers + srv-only …
jung-thomas Sep 11, 2026
a4ea1ec
Merge pull request #2256 from sap-tutorials/worktree-provenance-envel…
jung-thomas Sep 11, 2026
dff2fe4
docs(2245): correct assert authoring to rules.vr companion (matches c…
jung-thomas Sep 11, 2026
19da8f8
docs(2245): inline AssertSpecs in schema.cds (mirror CodeCheckSpecs, …
jung-thomas Sep 11, 2026
427128e
docs(2245): implementation plan for assert blocks (parse + persist)
jung-thomas Sep 11, 2026
38a49b9
fix(#2247): disable CSRF on /hcql/* approuter routes (Bearer M2M POST)
jung-thomas Sep 11, 2026
92e19c5
docs(#2247): acceptance criteria met
jung-thomas Sep 11, 2026
ce4c3ef
Merge remote-tracking branch 'origin/DEV' into worktree-hcql-reland-2247
jung-thomas Sep 11, 2026
ec62337
feat(2245): assert.ts parser + AssertBlock types (parse rules.vr [ASS…
jung-thomas Sep 11, 2026
889d4d3
fix(2245): warn on missing ###Type; assert per-input warn + parseExpe…
jung-thomas Sep 11, 2026
4680d03
feat(2245): emit steps[].asserts in frontmatter + compose preview parity
jung-thomas Sep 11, 2026
ce67b26
feat(2245): write <slug>.assert.json sidecar in fetch-tutorials
jung-thomas Sep 11, 2026
0e503e8
fix(2245): narrow AssertType at read time in assert.ts (Task 1 residu…
jung-thomas Sep 11, 2026
2df227a
build(#2247): re-stage db/last-dev/csn.json under CDS Build v10.1.0
jung-thomas Sep 11, 2026
11dd822
feat(2245): publish-asserts.js collect + POST /content/assert-specs
jung-thomas Sep 11, 2026
ec4e2c3
feat(2245): AssertSpecs entity + POST /content/assert-specs carry-for…
jung-thomas Sep 11, 2026
42b7fd9
fix(2245): add type-specific required-field validation to assertSpecP…
jung-thomas Sep 11, 2026
e8bad2a
build(#2247): sync srv-qa CAP deps to root (cds 10.1.0, hana 3.1.0)
jung-thomas Sep 11, 2026
6636fb2
docs(kg): design spec for learning-path reasoning API
jung-thomas Sep 11, 2026
97b5f3b
feat(2245): wire assert-spec publish into publish-content + route/qa …
jung-thomas Sep 11, 2026
4cb9873
fix(#2247): flip /hcql/* to CSRF-on default; document handshake
jung-thomas Sep 11, 2026
ff35cf7
Merge pull request #2257 from sap-tutorials/worktree-hcql-reland-2247
jung-thomas Sep 11, 2026
193607f
feat(kg): pure learning-path reasoning core (closure + topo-sort + de…
jung-thomas Sep 12, 2026
0a6daed
fix(kg): topoSort cycle-guard, satisfiesPrereqFor scope, concept-slug…
jung-thomas Sep 12, 2026
e29b465
feat(kg): graph-assembly adapter for learning-path (CQN snapshot)
jung-thomas Sep 12, 2026
ed97154
Merge remote-tracking branch 'origin/DEV' into worktree-assert-blocks…
jung-thomas Sep 12, 2026
b62d0e2
fix(kg): honor db handle, cover group/mission/next-best paths, warn o…
jung-thomas Sep 12, 2026
ab709a8
fix(2245): mark pre-canonicalized slug lookup in assertSpecPublishHan…
jung-thomas Sep 12, 2026
be35207
feat(kg): add KG_LEARNING_PATH_ENABLED db-setting flag (dev-only, def…
jung-thomas Sep 12, 2026
8901c8d
Merge pull request #2259 from sap-tutorials/worktree-assert-blocks-2245
jung-thomas Sep 12, 2026
92e1923
feat(kg): declare learningPath function + result types
jung-thomas Sep 12, 2026
2e39c7e
docs(2245): design spec for installable Skill bundle endpoint
jung-thomas Sep 12, 2026
1611d6c
docs(2245): implementation plan for Skill bundle endpoint
jung-thomas Sep 12, 2026
dba4f6f
feat(kg): learningPath handler — flag gate, request-time personalizat…
jung-thomas Sep 12, 2026
151d78b
feat(2245): register SKILL_BUNDLE_ENABLED feature flag
jung-thomas Sep 12, 2026
c466c75
feat(2245): generate verify.sh from assert specs
jung-thomas Sep 12, 2026
77c2c22
feat(kg): 'Your Learning Path' Vue island on tutorial/mission/group p…
jung-thomas Sep 12, 2026
43ead4c
feat(2245): compose SKILL.md from tutorial source + stamp
jung-thomas Sep 12, 2026
34dccfb
feat(2245): loadAssertSpecs reads + remaps AssertSpecs by slug
jung-thomas Sep 12, 2026
e07f7b9
fix(kg): strip group/mission slug prefix in learning-path island
jung-thomas Sep 12, 2026
5573237
feat(2245): freshness stamp (confidence + commit + optional jws)
jung-thomas Sep 12, 2026
6159c87
feat(kg): kg_learning_path MCP tool (delegates to learningPath)
jung-thomas Sep 12, 2026
e0ac708
feat(2245): skill bundle handler streams SKILL.md + verify.sh zip
jung-thomas Sep 12, 2026
fe2e536
fix(2245): 301 redirect on non-canonical slug + injectable buildSkill…
jung-thomas Sep 12, 2026
6275e9e
fix(kg): show learning-path sign-in nudge only to signed-out users
jung-thomas Sep 12, 2026
d2e1365
feat(2245): register GET /content/tutorials/:slug/skill route
jung-thomas Sep 12, 2026
f39f993
fix(2245): tighten route-ordering smoke assertion to any-HTML
jung-thomas Sep 12, 2026
a879170
feat(2245): allowlist /skill as srv-only in route-drift guard
jung-thomas Sep 12, 2026
32f9dd2
docs(kg): add learning-path implementation plan
jung-thomas Sep 12, 2026
94b3030
fix(2245): shell-quote curl -X method + echo label in verify.sh (inje…
jung-thomas Sep 12, 2026
4820d58
Merge pull request #2260 from sap-tutorials/worktree-kg-learning-path
jung-thomas Sep 12, 2026
d96acd0
fix(2245): rename lc->lcSlug in loadAssertSpecs for slug-lookup guard
jung-thomas Sep 12, 2026
b70456c
Merge pull request #2261 from sap-tutorials/feat/skill-bundle-2245
jung-thomas Sep 12, 2026
310f183
docs(ktt): design spec for Kasimir Teaches TLAs (KTT)
jung-thomas Sep 12, 2026
0fdbdbb
docs(ktt): implementation plan for Kasimir Teaches TLAs (KTT)
jung-thomas Sep 12, 2026
5697263
feat(ktt): add KTT_LESSON task type and KttLessons catalog entity
jung-thomas Sep 12, 2026
46c3839
feat(ktt): KttService.completeLesson records KTT_LESSON TaskRecord (i…
jung-thomas Sep 12, 2026
89e3a97
feat(ktt): syncProgress merges local and HANA progress on login
jung-thomas Sep 12, 2026
aed6a0e
feat(ktt): surface KTT lessons in MyCompletions as kind:ktt
jung-thomas Sep 12, 2026
303d520
feat(ktt): fail-open Kasimir banter action backed by @cap-js/ai
jung-thomas Sep 12, 2026
1949a9a
feat(ktt): register KTT_ENABLED db flag and gate /ktt write actions
jung-thomas Sep 12, 2026
4a63c86
feat(ktt): lesson schema, generator, and reviewed content data file
jung-thomas Sep 12, 2026
ab56b60
fix(ktt): correct CDL/LOB facts and harden lesson validation
jung-thomas Sep 12, 2026
3e52f92
feat(ktt): scaffold ktt Vue island and register Vite entry
jung-thomas Sep 12, 2026
b2a39f4
feat(ktt): pure lesson engine — scoring, XP, wrong-answer re-queue
jung-thomas Sep 12, 2026
e264e7b
feat(ktt): rigged SVG Kasimir with mood state machine + reduced-motion
jung-thomas Sep 12, 2026
6689e6c
feat(ktt): skill-tree map with lesson lock/unlock/done states
jung-thomas Sep 12, 2026
d4ccaf0
feat(ktt): lesson runner, results, local progress + best-effort serve…
jung-thomas Sep 12, 2026
04efe7e
fix(ktt): real XP emit, Results delta, immediate screen transition, O…
jung-thomas Sep 12, 2026
82b8aee
feat(ktt): Hugo page + layout with SSR shell and island mount
jung-thomas Sep 12, 2026
9465158
feat(ktt): add KTT to the Explore navigation menu
jung-thomas Sep 12, 2026
073fd89
build(ktt): generate ktt lessons as part of build:all
jung-thomas Sep 12, 2026
e9842df
test(ktt): post-deploy e2e smoke for /explore/ktt/ (self-skipping)
jung-thomas Sep 12, 2026
53f6cb2
fix(ktt): seed KttLessons catalog via generated CSV
jung-thomas Sep 12, 2026
3e56e5d
fix(ktt): fail closed when KTT_ENABLED is off
jung-thomas Sep 12, 2026
1f089b0
fix(ktt): use csrfFetch for POST actions; stage KttLessons csn snapshot
jung-thomas Sep 12, 2026
6cc8fcc
test(2245): pin provenance JWS verify to fixture clock (fix time-bomb)
jung-thomas Sep 12, 2026
a6ca135
build(ktt): regenerate csn + migration table with cds 10.1.0 compiler
jung-thomas Sep 12, 2026
6629109
feat(ktt): redraw Kasimir as recognizable grey tuxedo cat mascot
jung-thomas Sep 12, 2026
4d41fb4
build(ktt): stamp csn with lockfile-pinned compiler v7.0.1 (match CI)
jung-thomas Sep 12, 2026
ee9a204
feat(ktt): refine Kasimir — smaller warm eyes, blink in all moods, fi…
jung-thomas Sep 12, 2026
a85836c
feat(ktt): pass-3 Kasimir polish — remove double whiskers, per-eye co…
jung-thomas Sep 12, 2026
d19b816
Merge pull request #2262 from sap-tutorials/worktree-ktt-kasimir
jung-thomas Sep 12, 2026
49fa828
feat(security): origin-side cross-instance rate limiter (PR1, flag-off)
jung-thomas Sep 12, 2026
becb4cb
feat(security): edge-cache Fast-Purge hook + flag-coupled s-maxage — PR2
jung-thomas Sep 12, 2026
7b7b5fb
chore(agent): add quiet-run log wrapper + token-efficiency house rules
jung-thomas Sep 12, 2026
1a4cfc2
Merge pull request #2263 from sap-tutorials/feat-origin-abuse-protection
jung-thomas Sep 12, 2026
4f499f1
Merge pull request #2264 from sap-tutorials/feat-edge-fast-purge
jung-thomas Sep 12, 2026
fa3e11d
Merge pull request #2269 from sap-tutorials/token-efficiency-tooling
jung-thomas Sep 12, 2026
43f49ea
feat(security): WAF-equivalent input validation + GraphQL depth/compl…
jung-thomas Sep 12, 2026
97a33c4
Merge pull request #2273 from sap-tutorials/feat/2270-origin-abuse-pr3
jung-thomas Sep 12, 2026
356b3fb
feat(security): Origin load-shedding guard — PR4 (#2271)
jung-thomas Sep 13, 2026
95baabb
Merge pull request #2274 from sap-tutorials/feat/2271-loadshed-guard
jung-thomas Sep 13, 2026
41b28b8
chore: add live deploy-watcher.yaml descriptor (#2266)
jung-thomas Sep 13, 2026
3878daf
Merge pull request #2276 from sap-tutorials/feat/deploy-watcher-descr…
jung-thomas Sep 13, 2026
ab97228
fix(db): regenerate ChatSettings migration for semanticSearchEnabled …
jung-thomas Sep 13, 2026
6580f41
Merge pull request #2277 from sap-tutorials/fix/chatsettings-semantic…
jung-thomas Sep 13, 2026
ada92d2
fix(2245): declare gray-matter as runtime dependency
jung-thomas Sep 13, 2026
5367486
ci(guards): add packages: read so npm ci can read @sap-tutorials pkg
jung-thomas Sep 13, 2026
11584b8
Merge pull request #2278 from sap-tutorials/fix/skill-bundle-gray-mat…
jung-thomas Sep 13, 2026
a3b09f2
fix(retention): carry forward Vite shared chunks so island imports do…
jung-thomas Sep 13, 2026
8a0bdb3
Merge pull request #2279 from sap-tutorials/worktree-fix-retention-ch…
jung-thomas Sep 13, 2026
6af5ffe
fix(ktt): cap Kasimir size, add landing/coming-soon layout CSS
jung-thomas Sep 13, 2026
46603cc
Merge pull request #2280 from sap-tutorials/ktt-fix
jung-thomas Sep 13, 2026
3b7901c
fix(ktt): add /ktt approuter routes so the island can reach CAP
jung-thomas Sep 14, 2026
21682e5
Merge pull request #2281 from sap-tutorials/ktt-approuter-route
jung-thomas Sep 14, 2026
ece5767
fix(ktt): dark-mode contrast + lesson back button and honest labels
jung-thomas Sep 14, 2026
febb593
Merge pull request #2282 from sap-tutorials/fix/ktt-ux-dark-mode
jung-thomas Sep 14, 2026
37c5c61
fix(ktt): gate mastery on 70% pass threshold + surface XP levels/streak
jung-thomas Sep 14, 2026
38f2393
Merge pull request #2284 from sap-tutorials/fix/ktt-mastery-xp
jung-thomas Sep 14, 2026
8fef97b
feat(ktt): add ABAP, BDC, and new Unit 5 'SAP & AI' lessons
jung-thomas Sep 14, 2026
bfdeef7
Merge pull request #2289 from sap-tutorials/fix/ktt-ai-acronyms
jung-thomas Sep 14, 2026
7789d25
fix(publish-content): retry transient HANA pool-timeout 500s (#2286)
jung-thomas Sep 14, 2026
ad82dac
Merge pull request #2290 from sap-tutorials/fix/2286-publish-begin-retry
jung-thomas Sep 14, 2026
68a0073
fix(list-fence): repair list-continuation fences indented 4-7 spaces …
jung-thomas Sep 14, 2026
e68edec
Merge pull request #2291 from sap-tutorials/worktree-fix-2287-list-fe…
jung-thomas Sep 14, 2026
9a5ee61
fix(images): re-warm images on slug-targeted rebuilds so in-place scr…
jung-thomas Sep 14, 2026
4fb9053
Merge pull request #2292 from sap-tutorials/fix/2288-republish-image-…
jung-thomas Sep 14, 2026
593554e
fix(admin): correct NoAccess contact info (#2293)
jung-thomas Sep 14, 2026
8d11d68
fix(display-app): QR points to same-origin /app-space with eventId
jung-thomas Sep 14, 2026
05b44f0
fix(display-app): read getEventBuckets object shape, tolerate zero co…
jung-thomas Sep 14, 2026
f411705
Merge pull request #2299 from sap-tutorials/worktree-fix-2294-display…
jung-thomas Sep 14, 2026
e21d3a2
Merge pull request #2297 from sap-tutorials/worktree-fix-2293-noacces…
jung-thomas Sep 14, 2026
a2b169b
Merge pull request #2298 from sap-tutorials/fix/2295-display-app-even…
jung-thomas Sep 14, 2026
0f49051
feat(events): render Event description Markdown as safe HTML on App S…
jung-thomas Sep 14, 2026
8c7a249
perf(concepts): parallelize /build/concepts link-table reads
jung-thomas Sep 14, 2026
c929478
Merge pull request #2302 from sap-tutorials/perf/build-concepts-parallel
jung-thomas Sep 14, 2026
1052296
fix(mta): add srv/lib/markdown.js to srv-qa cp list (#2296)
jung-thomas Sep 14, 2026
1ec9672
Merge pull request #2301 from sap-tutorials/worktree-event-desc-markd…
jung-thomas Sep 14, 2026
5a6da23
feat(admin): Copy Mission deep-copy action + LR button (#2300)
jung-thomas Sep 14, 2026
acd128b
fix(admin): canonicalize slug in copyMission uniqueSlug probe
jung-thomas Sep 14, 2026
6c24d3e
Merge pull request #2303 from sap-tutorials/feat/copy-mission-2300
jung-thomas Sep 14, 2026
f4daf8a
chore(release): 1.26.0 — What's New digest + version bump
jung-thomas Sep 14, 2026
9d766c7
Merge pull request #2304 from sap-tutorials/worktree-release-1.26.0
jung-thomas Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .deploy/mta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ID: tutorials-ims
# Bump this on each release you deploy — it's the version shown by `cf mtas`
# and in the mtar filename (tutorials-ims_<version>.mtar). Deploy is manual:
# `cd .deploy && mbt build && cf deploy mta_archives/tutorials-ims_<version>.mtar -e ../deploy/<env>.mtaext -f`.
version: 1.25.0
version: 1.26.0

# Top-level parameters (overridable per-env via deploy/<env>.mtaext).
parameters:
Expand Down Expand Up @@ -178,7 +178,7 @@ modules:
- cp -r ../../hugo/assets ./hugo/assets
- cp -r ../../hugo/data ./hugo/data
- cp -r ../../hugo/i18n ./hugo/i18n
- bash -c "mkdir -p srv/jobs && mkdir -p srv/handlers && mkdir -p srv/lib/branch && mkdir -p srv/lib/runtime-config && mkdir -p srv/lib/prompts && mkdir -p srv/lib/kg && mkdir -p srv/mcp/prompts && cp ../../srv/lib/branch/condition.js ../../srv/lib/branch/engine.js ../../srv/lib/branch/ranker.js ../../srv/lib/branch/user-state.js ../../srv/lib/branch/loaders.js ../../srv/lib/branch/mission-detail.js ../../srv/lib/branch/slug-key.js ../../srv/lib/branch/decide.js ../../srv/lib/branch/joule-tool.js ../../srv/lib/branch/branch-telemetry.js ../../srv/lib/branch/group-by-alt.js ../../srv/lib/branch/profile-fields.js ../../srv/lib/branch/profile-override.js srv/lib/branch/ && cp ../../srv/lib/runtime-config/kg-settings.js ../../srv/lib/runtime-config/ui-events-settings.js ../../srv/lib/runtime-config/search-settings.js ../../srv/lib/runtime-config/navigator-settings.js ../../srv/lib/runtime-config/display-settings.js ../../srv/lib/runtime-config/tenant-settings.js ../../srv/lib/runtime-config/alert-settings.js srv/lib/runtime-config/ && cp ../../srv/lib/kg/on-demand-enqueue.js ../../srv/lib/kg/on-demand-cosine-rank.js srv/lib/kg/ && cp ../../srv/lib/credstore.js ../../srv/lib/secret-resolver.js ../../srv/lib/content-store.js ../../srv/lib/tutorial-markdown.js ../../srv/lib/content-delta-flags.js ../../srv/lib/content-cache-coherence.js ../../srv/lib/edge-cache-headers.js ../../srv/lib/content-publish-session.js ../../srv/lib/resolve-tutorial-author.js ../../srv/lib/_tutorials-table.js ../../srv/lib/catalog-renderer.js ../../srv/lib/catalog-data.js ../../srv/lib/catalog-mission-hierarchy.js ../../srv/lib/chrome-shell.js ../../srv/lib/pipeline-log.js ../../srv/lib/legacy-id.js ../../srv/lib/embedding-pipeline.js ../../srv/lib/step-text-extractor.js ../../srv/lib/embedding-client.js ../../srv/lib/step-vectors.js ../../srv/lib/user-progress.js ../../srv/lib/co-completion.js ../../srv/lib/tutorial-centroid.js ../../srv/lib/tag-label-map.js ../../srv/lib/code-check-tool.js ../../srv/lib/code-check-prompt.js ../../srv/lib/code-check-handler.js ../../srv/lib/code-check-llm.js ../../srv/lib/code-check-step-loader.js ../../srv/lib/code-check-spec-publish.js ../../srv/lib/validate-answer-spec-publish.js ../../srv/lib/category-classifier.js ../../srv/lib/category-classifier-llm.js ../../srv/lib/category-seed-embeddings.js ../../srv/lib/build-catalog-categories.js ../../srv/lib/chat-settings-resolver.js ../../srv/lib/kg-extract.js ../../srv/lib/kg-queries.js ../../srv/lib/kg-projection.js ../../srv/lib/kg-similarity.js ../../srv/lib/kg-cycles.js ../../srv/lib/kg-graph-rebuild.js ../../srv/lib/kg-sparql-client.js ../../srv/lib/kg-merge-pair.js ../../srv/lib/kg-concept-loader.js ../../srv/lib/kg-neighborhood-cache.js ../../srv/lib/kg-neighborhood-merge.js ../../srv/lib/kg-neighborhood-full-helpers.js ../../srv/lib/kg-other-resources-loader.js ../../srv/lib/kg-stamp-meta-text.js ../../srv/lib/kg-tutorial-teaches-map.js ../../srv/lib/kg-resource-type-config.js ../../srv/lib/kg-meta-formatters.js ../../srv/lib/discovery-mission-categories.js ../../srv/lib/external-content-ttl.js ../../srv/lib/recompute-tutorial-progress-bulk-sql.js ../../srv/lib/youtube-fetcher.js ../../srv/lib/homepage-events-merger.js ../../srv/lib/homepage-rss-fetcher.js ../../srv/lib/rss-parse.js ../../srv/lib/community-blogs-fetcher.js ../../srv/lib/community-blog-source-defaults.js ../../srv/lib/community-blogs-classifier.js ../../srv/lib/safe-fetch.js ../../srv/lib/curl-transport.js ../../srv/lib/khoros-transport.js ../../srv/lib/explainer-generator.js ../../srv/lib/_token-cost.js ../../srv/lib/metrics.js ../../srv/lib/alerting.js ../../srv/lib/relevance-classifier.js ../../srv/lib/relevance-seed-embeddings.js ../../srv/lib/relevance-keyword-rules.js ../../srv/lib/canonicalize-link.js ../../srv/lib/detect-language-en.js ../../srv/lib/kg-community-coverage.js ../../srv/lib/page-key-map.js ../../srv/lib/page-fallback.js ../../srv/lib/task-record-submission-id.js ../../srv/lib/image-store.cjs ../../srv/lib/image-ingest.cjs ../../srv/lib/image-source-handler.js ../../srv/lib/img-cdn-fetch.cjs ../../srv/lib/img-cdn-retry.cjs ../../srv/lib/image-warm-utils.js ../../srv/lib/attachment-store.cjs ../../srv/lib/attachment-ingest.cjs ../../srv/lib/attachment-mime.cjs ../../srv/lib/attachment-warm-utils.js ../../srv/lib/attachment-source-handler.js ../../srv/lib/attachment-ingest-handler.js ../../srv/lib/contributors-publish.js ../../srv/lib/validation-rules-publish.js ../../srv/lib/topics-query.js ../../srv/lib/topic-slug.js ../../srv/lib/tag-md-format.js ../../srv/lib/semaphore-tags.js ../../srv/lib/publish-channels.js ../../srv/lib/media-diet-picks.js ../../srv/lib/media-diet-export.js ../../srv/lib/build-channel-detail.js ../../srv/lib/channel-detail-render.js ../../srv/lib/build-channel-atlas.js ../../srv/lib/island-manifest.json srv/lib/ && mkdir -p srv/lib/channels && cp ../../srv/lib/channels/normalize.cjs srv/lib/channels/ && mkdir -p srv/lib/feature-flags && cp ../../srv/lib/feature-flags/db-flags.js ../../srv/lib/feature-flags/registry.js srv/lib/feature-flags/ && cp ../../srv/handlers/categories-after-hooks.js ../../srv/handlers/completion-path-items-altgroup.js srv/handlers/ && mkdir -p srv && cp ../../srv/content-moderation-service.js srv/ && cp ../../srv/jobs/consolidate-concepts-job.js ../../srv/jobs/extract-concepts-job.js ../../srv/jobs/job-lock.js ../../srv/jobs/secret-expiry-check.js ../../srv/jobs/homepage-link-health.js ../../srv/jobs/kg-ondemand-job.js ../../srv/jobs/community-blogs-fetch-job.js ../../srv/jobs/community-blogs-classify-job.js ../../srv/jobs/fetch-news-job.js srv/jobs/ && cp ../../srv/lib/prompts/explainer-verb.md ../../srv/lib/prompts/explainer-shelf.md ../../srv/lib/prompts/explainer-shelf-entry.md ../../srv/lib/prompts/community-blogs-classifier.md srv/lib/prompts/ && cp ../../srv/mcp/prompts/summarize_mission_for_beginner.md ../../srv/mcp/prompts/generate_lab_exercise.md ../../srv/mcp/prompts/explain_concept.md ../../srv/mcp/prompts/suggest_learning_path.md srv/mcp/prompts/"
- bash -c "mkdir -p srv/jobs && mkdir -p srv/handlers && mkdir -p srv/lib/branch && mkdir -p srv/lib/runtime-config && mkdir -p srv/lib/prompts && mkdir -p srv/lib/kg && mkdir -p srv/mcp/prompts && cp ../../srv/lib/branch/condition.js ../../srv/lib/branch/engine.js ../../srv/lib/branch/ranker.js ../../srv/lib/branch/user-state.js ../../srv/lib/branch/loaders.js ../../srv/lib/branch/mission-detail.js ../../srv/lib/branch/slug-key.js ../../srv/lib/branch/decide.js ../../srv/lib/branch/joule-tool.js ../../srv/lib/branch/branch-telemetry.js ../../srv/lib/branch/group-by-alt.js ../../srv/lib/branch/profile-fields.js ../../srv/lib/branch/profile-override.js srv/lib/branch/ && cp ../../srv/lib/runtime-config/kg-settings.js ../../srv/lib/runtime-config/ui-events-settings.js ../../srv/lib/runtime-config/search-settings.js ../../srv/lib/runtime-config/navigator-settings.js ../../srv/lib/runtime-config/display-settings.js ../../srv/lib/runtime-config/tenant-settings.js ../../srv/lib/runtime-config/alert-settings.js ../../srv/lib/runtime-config/load-shed-settings.js srv/lib/runtime-config/ && cp ../../srv/lib/kg/on-demand-enqueue.js ../../srv/lib/kg/on-demand-cosine-rank.js srv/lib/kg/ && cp ../../srv/lib/credstore.js ../../srv/lib/secret-resolver.js ../../srv/lib/content-store.js ../../srv/lib/tutorial-markdown.js ../../srv/lib/content-delta-flags.js ../../srv/lib/content-cache-coherence.js ../../srv/lib/edge-cache-headers.js ../../srv/lib/content-publish-session.js ../../srv/lib/resolve-tutorial-author.js ../../srv/lib/_tutorials-table.js ../../srv/lib/catalog-renderer.js ../../srv/lib/markdown.js ../../srv/lib/catalog-data.js ../../srv/lib/catalog-mission-hierarchy.js ../../srv/lib/chrome-shell.js ../../srv/lib/pipeline-log.js ../../srv/lib/legacy-id.js ../../srv/lib/embedding-pipeline.js ../../srv/lib/step-text-extractor.js ../../srv/lib/embedding-client.js ../../srv/lib/step-vectors.js ../../srv/lib/user-progress.js ../../srv/lib/co-completion.js ../../srv/lib/tutorial-centroid.js ../../srv/lib/tag-label-map.js ../../srv/lib/code-check-tool.js ../../srv/lib/code-check-prompt.js ../../srv/lib/code-check-handler.js ../../srv/lib/code-check-llm.js ../../srv/lib/code-check-step-loader.js ../../srv/lib/code-check-spec-publish.js ../../srv/lib/assert-spec-publish.js ../../srv/lib/validate-answer-spec-publish.js ../../srv/lib/category-classifier.js ../../srv/lib/category-classifier-llm.js ../../srv/lib/category-seed-embeddings.js ../../srv/lib/build-catalog-categories.js ../../srv/lib/chat-settings-resolver.js ../../srv/lib/kg-extract.js ../../srv/lib/kg-queries.js ../../srv/lib/kg-projection.js ../../srv/lib/kg-similarity.js ../../srv/lib/kg-cycles.js ../../srv/lib/kg-graph-rebuild.js ../../srv/lib/kg-sparql-client.js ../../srv/lib/kg-merge-pair.js ../../srv/lib/kg-concept-loader.js ../../srv/lib/kg-neighborhood-cache.js ../../srv/lib/kg-neighborhood-merge.js ../../srv/lib/kg-neighborhood-full-helpers.js ../../srv/lib/kg-other-resources-loader.js ../../srv/lib/kg-stamp-meta-text.js ../../srv/lib/kg-tutorial-teaches-map.js ../../srv/lib/kg-resource-type-config.js ../../srv/lib/kg-meta-formatters.js ../../srv/lib/discovery-mission-categories.js ../../srv/lib/external-content-ttl.js ../../srv/lib/recompute-tutorial-progress-bulk-sql.js ../../srv/lib/youtube-fetcher.js ../../srv/lib/homepage-events-merger.js ../../srv/lib/homepage-rss-fetcher.js ../../srv/lib/rss-parse.js ../../srv/lib/community-blogs-fetcher.js ../../srv/lib/community-blog-source-defaults.js ../../srv/lib/community-blogs-classifier.js ../../srv/lib/safe-fetch.js ../../srv/lib/curl-transport.js ../../srv/lib/khoros-transport.js ../../srv/lib/explainer-generator.js ../../srv/lib/_token-cost.js ../../srv/lib/metrics.js ../../srv/lib/alerting.js ../../srv/lib/relevance-classifier.js ../../srv/lib/relevance-seed-embeddings.js ../../srv/lib/relevance-keyword-rules.js ../../srv/lib/canonicalize-link.js ../../srv/lib/detect-language-en.js ../../srv/lib/kg-community-coverage.js ../../srv/lib/page-key-map.js ../../srv/lib/page-fallback.js ../../srv/lib/task-record-submission-id.js ../../srv/lib/image-store.cjs ../../srv/lib/image-ingest.cjs ../../srv/lib/image-source-handler.js ../../srv/lib/img-cdn-fetch.cjs ../../srv/lib/img-cdn-retry.cjs ../../srv/lib/image-warm-utils.js ../../srv/lib/attachment-store.cjs ../../srv/lib/attachment-ingest.cjs ../../srv/lib/attachment-mime.cjs ../../srv/lib/attachment-warm-utils.js ../../srv/lib/attachment-source-handler.js ../../srv/lib/attachment-ingest-handler.js ../../srv/lib/contributors-publish.js ../../srv/lib/validation-rules-publish.js ../../srv/lib/topics-query.js ../../srv/lib/topic-slug.js ../../srv/lib/tag-md-format.js ../../srv/lib/semaphore-tags.js ../../srv/lib/publish-channels.js ../../srv/lib/media-diet-picks.js ../../srv/lib/media-diet-export.js ../../srv/lib/build-channel-detail.js ../../srv/lib/channel-detail-render.js ../../srv/lib/build-channel-atlas.js ../../srv/lib/island-manifest.json ../../srv/lib/provenance-handlers.js ../../srv/lib/provenance-envelope.js ../../srv/lib/provenance-data.js ../../srv/lib/provenance-keys.js ../../srv/lib/provenance-freshness.js ../../srv/lib/fast-purge.js ../../srv/lib/load-shed.js srv/lib/ && mkdir -p srv/lib/channels && cp ../../srv/lib/channels/normalize.cjs srv/lib/channels/ && mkdir -p srv/lib/feature-flags && cp ../../srv/lib/feature-flags/db-flags.js ../../srv/lib/feature-flags/registry.js srv/lib/feature-flags/ && cp ../../srv/handlers/categories-after-hooks.js ../../srv/handlers/completion-path-items-altgroup.js srv/handlers/ && mkdir -p srv && cp ../../srv/content-moderation-service.js srv/ && cp ../../srv/jobs/consolidate-concepts-job.js ../../srv/jobs/extract-concepts-job.js ../../srv/jobs/job-lock.js ../../srv/jobs/secret-expiry-check.js ../../srv/jobs/homepage-link-health.js ../../srv/jobs/kg-ondemand-job.js ../../srv/jobs/community-blogs-fetch-job.js ../../srv/jobs/community-blogs-classify-job.js ../../srv/jobs/fetch-news-job.js srv/jobs/ && cp ../../srv/lib/prompts/explainer-verb.md ../../srv/lib/prompts/explainer-shelf.md ../../srv/lib/prompts/explainer-shelf-entry.md ../../srv/lib/prompts/community-blogs-classifier.md srv/lib/prompts/ && cp ../../srv/mcp/prompts/summarize_mission_for_beginner.md ../../srv/mcp/prompts/generate_lab_exercise.md ../../srv/mcp/prompts/explain_concept.md ../../srv/mcp/prompts/suggest_learning_path.md srv/mcp/prompts/"
- bash -c "node -e \"const p=require('./package.json'); p.dependencies=Object.assign(p.dependencies||{},{cheerio:'^1.2.0','@sap-ai-sdk/foundation-models':'^2.10.0'}); require('fs').writeFileSync('./package.json', JSON.stringify(p,null,2));\""
properties:
EXPOSE_CAP_UI: false
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/rebuild-content-qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,24 @@ jobs:
channel: qa
min-slugs: '1'

# #2288 — refresh the changed tutorial's images. Image-only edits (same
# filename) don't change the HTML/markdown hash, so publish-content's delta
# drops the slug and warmImagesLive never fires — the HANA image store keeps
# stale bytes. Re-warm just this slug's images: backfill re-fetches from
# GitHub and POSTs bytes; the srv ingest content-hash-dedups (re-stores only
# changed images). Slug-targeted only — a full rebuild would re-fetch every
# image. Skipped on a full QA rebuild (empty slug) and on force-publish
# (which already republishes + warms every slug). Non-fatal: image refresh
# must never fail the content rebuild.
- name: Refresh QA tutorial images (slug-targeted)
if: ${{ !inputs.force-publish && (github.event.client_payload.slug || inputs.slug) }}
continue-on-error: true
run: npx tsx scripts/backfill-images.ts --channel qa --slug "${{ github.event.client_payload.slug || inputs.slug }}"
env:
CAP_QA_BASE_URL: ${{ secrets.CAP_SRV_URL_QA }}
CONTENT_API_KEY_QA: ${{ secrets.CONTENT_API_KEY_QA }}
GITHUB_TOKEN: ${{ steps.app-token.outputs.token || secrets.TUTORIAL_FETCH_TOKEN || secrets.TUTORIALS_GITHUB_TOKEN }}

- name: Summary
run: |
echo "### QA Content Rebuild Complete" >> "$GITHUB_STEP_SUMMARY"
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/rebuild-content.yml
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,27 @@ jobs:
channel: ${{ steps.env.outputs.target }}
min-slugs: '1'

# #2288 — same-filename image byte changes are invisible to the publish
# delta detector: publish hashes rendered HTML + source markdown, never the
# image bytes, so a screenshot edited in place (unchanged filename → unchanged
# /img-cdn URL) never triggers a republish and the stale image is served
# indefinitely. On a slug-targeted rebuild, re-warm just that tutorial's
# images through the content-aware ingest endpoint (POST /content/image
# dedups on image bytes), so changed bytes are re-stored while unchanged
# ones report 'unchanged'. Best-effort: a warm failure must never fail the
# content rebuild. Scoped to slug-targeted (not full) per #2288 decision —
# full rebuilds already re-warm the whole catalog elsewhere. CAP_BASE_URL is
# the already target-resolved srv url; the QA target needs its own key.
- name: Refresh tutorial images (slug-targeted)
if: ${{ steps.publish.outcome == 'success' && steps.mode.outputs.effective_mode == 'slug-targeted' && inputs.force-publish != true }}
continue-on-error: true
env:
CAP_BASE_URL: ${{ steps.srv.outputs.srv_url }}
CONTENT_API_KEY: ${{ steps.env.outputs.target == 'qa' && secrets.CONTENT_API_KEY_QA || secrets.CONTENT_API_KEY }}
GITHUB_TOKEN: ${{ steps.app-token.outputs.token || secrets.TUTORIALS_GITHUB_TOKEN }}
REFRESH_SLUG: ${{ inputs.slug || steps.mode.outputs.dispatch_slug }}
run: npx tsx scripts/backfill-images.ts --slug "$REFRESH_SLUG"

- name: Purge orphan tutorials
id: purge
if: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/static-guards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,6 @@ approuter/static/.well-known/oauth-protected-resource
test-results/
playwright-report/
.playwright-auth-state.json

# quiet-run wrapper full logs — local scrollback capture, never committed.
.quiet-logs/
Loading
Loading