DataTalksClub / DataTalksClub/website
Add an offline pinned FAQ adapter and exact feed projection
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Parent: #42
Normative authority:
- 03 — source ownership and FAQ adapter
- 03 — public provenance boundary
- 02 — FAQ paths, fragments, and JSON compatibility
- Application boundaries: source parsing belongs in
content_sync; public readers incontentmust not import the adapter. - Verification strategy
Product outcome
Provide one deterministic, network-free dtc-faq adapter and five-field JSON-feed projection from an already verified immutable FAQ checkout. It must prove both the accepted checked baseline and the current green source without changing the public FAQ reader, rendering a public edit link, or introducing any direct-sync/activation behavior.
The accepted target input is exactly:
- repository
DataTalksClub/faq; - branch
main; - commit
3a170c98ad6af394408595f697ce6624ffab155f; - tree
6b00fa01f1bc9fee4147b4f6e30f685a429f98c8; - source CI run 33236963075, successful;
- selected roots
_questions/andimages/only.
The adapter receives a caller-supplied local checkout plus the expected immutable commit/tree identity. It performs no clone, fetch, remote-head lookup, provider call, hook, filter, repository-code execution, database mutation, or public-reader switch.
Evidence baseline and target census
The checked website projection on origin/main@face8e4808d65afbf0374d1ced7a88079950d663 is content/faq_projection.json SHA-256 7b6e5723b2ab0cf453254c10fb06a08175ca2bee5b9c65d98cc0534acfe8f209. It pins DataTalksClub/faq@c8da1deea9e24945922702994de101dd90a5380a, tree f880b4b63cdd1b213bd1303d8874e4ce02e63965, with:
- 6 courses, 70 populated sections, 1,401 questions;
- per-course counts in public order: Data Engineering 404, Stock Markets Analytics 93, Machine Learning 471, LLM 139, AI Dev Tools 41, MLOps 253;
- 101 image declarations resolving to 99 unique referenced assets; and
- two management-only CSS assets plus all source images copied separately by the historical projection, outside this feed-only slice.
The target commit has:
- 6 course metadata files, 74 declared sections, 70 populated sections, 1,406 questions;
- per-course counts in the same public order: 404, 93, 471, 144, 41, 253;
- 1,406 non-empty questions and answers, 101 image declarations, 99 unique referenced image paths, and 136 source image files;
- five added LLM questions:
5cc511f85b,2fed4b176c,920bb7ead8,8471c98e1f, and670737acd7; - answer-only changes to
eae0fb50aaand8fd8cd336d; no metadata or image change from the accepted baseline; - four accepted equal-
sort_ordergroups, resolved deterministically by source filename; and - two YAML numeric-looking IDs,
6739977244and9506089527, normalized to ten-character strings as required by the fragment/feed contract.
Four declared sections currently contain no question: ai-dev-tools-zoomcamp/module-6, stock-markets-analytics-zoomcamp/misc, llm-zoomcamp/module-4-homework, and llm-zoomcamp/module-6-homework. Preserve all 74 declarations and their order in management candidate data, but the flattened feed and its populated-section count contain only records from the 70 populated sections.
Adapter and candidate contract
Add a content_sync-owned immutable FAQ contract, adapter, bounded diagnostics, and focused fixtures/tests. The result contains:
- source stable ID, repository, branch, commit SHA, tree SHA, adapter/parser schema versions, selected-input digest, counts, and deterministic bundle/feed digests;
- courses in this exact public order:
data-engineering-zoomcamp,stock-markets-analytics-zoomcamp,machine-learning-zoomcamp,llm-zoomcamp,ai-dev-tools-zoomcamp,mlops-zoomcamp; - each course’s exact slug, display name, ordered declared sections, and management-only Slack/Telegram/comment metadata where present;
- each section’s exact ID, name, declaration order, optional management comment, populated state, and ordered questions;
- each question’s normalized ten-character string ID, course and section identity/name, positive integer
sort_order, exact question, exact raw Markdown answer, normalized source path, and management-only moving-mainedit URL; - each declared image’s ID, description, normalized source path, stable candidate public path, size, media type, and SHA-256; duplicate references to the same source asset share one asset identity; and
- feed projections containing only
{id,course,section,question,answer}in section order and then(sort_order, source filename byte order).
The courses.json projection contains only {course,course_name,path,questions_count} in the exact course order above. Its legacy path remains /json/<course>.json even though the website serves the compatibility route beneath /faq/json/.
Question/answer bytes are decoded as strict UTF-8 and preserved as source text after frontmatter separation; Jinja/Liquid/dbt-looking text is data and is never evaluated. Valid Unicode content is preserved, not normalized or rewritten. Structural identifiers and paths remain bounded ASCII.
The current two numeric YAML ID scalars are a reviewed compatibility exception: accept a non-boolean integer only when its canonical decimal representation is exactly ten characters, then normalize it to a string. Every other ID type, length, or character set fails. Do not add general scalar coercion.
Validation and failure behavior
- Accept only the exact metadata/question/image schemas exercised by the target checkout. Unknown structural keys, unknown courses/sections, duplicate course/section/question identities, duplicate per-question image IDs, invalid/blank question or answer, invalid sort order, or conflicting asset identity fail closed.
- Metadata is authoritative for course/section membership and order. A question under an undeclared course/section fails. Equal positive
sort_ordervalues are allowed and use the filename tie-break above. - Resolve images only below
images/<same-course>/with the accepted.png/.jpgmedia types. Missing, symlinked, traversal, absolute, cross-course, remote, wrong-type, oversized, or checksum-conflicting assets fail. Unreferenced source images are inventory evidence, not candidate assets. - Use safe, bounded YAML event scanning/construction. Reject aliases, unsafe tags/types, duplicate mapping keys, invalid UTF-8, path/control-character violations, depth/node/file-count/byte/time overruns, symlinks, gitlinks, and unexpected selected-root file types.
- Bounds must cover the measured target (1,551 selected files, 10,472,655 selected bytes, largest file 862,721 bytes) with explicit reviewed headroom; they must not be unbounded or inferred from the checkout at runtime.
- Failures return stable code plus bounded normalized relative path only. Do not include source content, raw YAML, exception text, absolute paths, tokens, credentials, or provider payloads.
- A failed parse returns no partial bundle/feed and changes no checked projection, public response, model, or prior artifact.
- Two exact runs over the same checkout produce byte-identical canonical bundle/feed evidence and digests regardless of filesystem enumeration order.
Public provenance boundary
edit_url, repository, branch, revision, tree, checksum, source path, diagnostics, and source-status evidence are management/build data only. They must not occur in FAQ HTML, either JSON feed, public structured data, sitemap/search output, or other anonymous response.
This issue must retain the current public guarantee: /faq/ and /faq/<course>.html show no “Edit on GitHub” control and no source/revision disclosure. The public five-field question feed and four-field course feed contain no provenance field. Do not add an edit-link browser scenario: public edit-link behavior is forbidden by specification 03.
Acceptance criteria
- The network-free adapter rejects a mismatched repository/branch/commit/tree and never invokes network, repository hooks/filters, or source code.
- Exact replay of
c8da1de...produces 6/70/1,401/99 and payload-equal course/question feed arrays to the checked projection, including ten-character string IDs and exact order. - Exact replay of
3a170c...produces 6 courses, 74 declared/70 populated sections, 1,406 questions, 101 declarations/99 referenced assets, the exact per-course counts and seven-record delta above, and deterministic evidence on two runs. - Course, metadata-section, question, equal-sort tie, raw Markdown, valid Unicode, image-reference, and feed-field/order contracts are covered by focused tests.
- The two exact numeric-ID exceptions normalize to strings; booleans, floats, nulls, sequences, mappings, other integers, malformed strings, and duplicate IDs fail.
- Traversal/symlink/gitlink, unknown or cross-course paths, unsafe YAML, duplicate keys, missing/invalid metadata, missing/conflicting assets, invalid UTF-8/structural controls, and every resource bound fail with content-free deterministic diagnostics and no partial result.
- Repository tests prove candidate management provenance is absent from both feed projections and existing anonymous FAQ HTML/JSON responses.
- A versioned selective-CI plan records exact base/head, graph/plan digests, all dispositions, and fresh focused/full evidence required by the graph.
Verification scenarios
- Parse the accepted baseline and target immutable checkouts twice with deliberately shuffled filesystem enumeration; compare complete canonical evidence/digests and the exact census/delta.
- Compare baseline feed arrays against
content/faq_projection.json, including the fixed course order, raw answers, four equal-sort groups, and two normalized numeric IDs. - Use bounded fixtures for every schema/type/path/YAML/resource denial above and assert stable diagnostic code/path with no raw input leakage.
- Inspect existing anonymous FAQ HTML, course feed, and course-index feed for absence of edit URLs, repository names, revisions, checksums, and source paths.
Browser
The graph-selected backend-only browser tier is required. Run make test-playwright-smoke against the exact frozen candidate and retain plan-bound evidence. This is regression coverage for the shared/test-infrastructure impact; it does not authorize a page, route, payload, or rendering change and adds no issue-specific public browser scenario.
Screenshots
not_applicable for this child: it adds an offline adapter/evidence surface and must not change a template, public route, response payload, CSS, asset route, or checked projection. Existing request-level provenance-denial regression tests are required. Any implementation that changes public rendering or feeds is out of scope and must return to PM for a separate render-impact issue with desktop/mobile screenshots.
Dependencies and downstream work
No open implementation dependency. The accepted checked projection and immutable source checkout are the inputs; this slice deliberately does not depend on #38’s direct-sync models, #273–#278, a provider credential, or a database/public-reader decision.
Downstream only:
- parent #42 retains the public-page/current-pin lifecycle and will need a separately groomed checked-projection/public-regression slice after this adapter is accepted;
- #274 may later consume the adapter from the generic network-free direct-sync runner;
- #276 owns any database-backed public-reader cutover;
- #44 owns search integration.
A merge for this child uses Refs #42 and Closes #293; it does not close #42 or claim source activation.
Non-goals
No source clone/fetch/webhook/reconciliation, credentials, durable jobs, source lock, direct database upsert, ContentRelease, SyncLog, activation/rollback, Studio/admin API, search/graph indexing, public-reader or checked-projection switch, public page/template/asset/CSS change, new public route or field, public edit link, source repository mutation, provider/production access, or execution of DataTalksClub/faq code.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read the linked adapter, provenance, compatibility, and verification specifications, then inspect the existing content_sync entry points and content/faq_projection.json. Start with the accepted baseline and target checkout requirements, and use the stated focused fixtures/tests plus make test-playwright-smoke for verification. Done means deterministic offline evidence and exact feed projections without public FAQ or provenance changes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100