Przejdź do głównej zawartości

v2.0.6 Survey construction

· 9 min aby przeczytać
John Renfrew
Programmer and data architect

Version 2.0.6 Survey JS construction

Survey Question Prefix Index

informacja

current draft document

Reference index of every question-name prefix/convention used in this project's SurveyJS task forms — what it's for, who can see/edit it, and how that's enforced. Pulled together from praxis-consolidated-playbook.md, this session's MQL/LLn work, and the real TaskClient.tsx. Status per entry: Confirmed (seen live or in real code), Designed (agreed, not yet built), Placeholder (reserved, no implementation), or Open (unresolved as of this index).


1. Hidden/system fields — never rendered as questions

All live in a hidden base_panel, injected/overridden by TaskClient.tsx on load — these are the security boundary; stored survey data can't override them.

FieldHoldsNotes
studentIDStudent's IDSet by whichever role's first save creates the record
moduleIDModule contextSee "Fixed" vs "Floating" module assignment in the consolidated playbook
superIDSupervisor's ID once claimedEmpty = no supervisor yet. Drives SQ*/Q* cascade
markerIDMarker's ID once claimedEmpty = no marker yet. Drives MQ* cascade
filesIDComma-separated key:uid pairse.g. "UL1:4183AAE7-...,UL2:..." — plain string, not JSON despite an old debug stub in TaskClient.tsx assuming otherwise
altHide3-state (null/1/2)Placement Review only — controls new-Q/SQ/MQ visibility for that mid/end-year twin-record flow. Purely display, no effect on routing/state
observerObserver's IDNo visibleIf/enableIf cascade defined yet — observer role exists in TaskClient.tsx (isObserver) but has no confirmed question-visibility convention of its own

2. Role-owned answer prefixes

Confirmed — standard three-role set, praxis-consolidated-playbook.md:

PrefixRoleVisibilityEditability
Q1, Q2, ...StudentAlways visibleenableIf: "{superID} empty" (JSON-authored)
SQ1, SQ2, ...SupervisorvisibleIf: "{superID} notempty"enableIf: "{markerID} empty" (JSON-authored)
MQ1 (exact)Marker — publicisMarker || (isStudent && task.state === "marked")code-enforced, not JSON visibleIfMarker-only
MQ2, MQ3, ...Marker — privateisMarker only, at any task.statecode-enforcedMarker-only
  • MQ1's public/private split and the switch to code-enforced visibility (rather than trusting each question's own visibleIf) is this session's design, superseding the older documented convention that all MQ* visibility ran entirely off {markerID} notempty in the JSON.
  • Generic editability rule (this session, code-enforced): each role edits only its own prefix; every other role gets readOnly, including roles that own no prefix at all (observer, and the future tutor). Not locked by task.state for MQ* — deliberately left open-ended (transient internal commentary).
  • SQ*/MQ* visibility has no relationship to task.statestate only drives TaskClient.tsx's own UI locking (upload buttons, autosave, survey read-only mode), confirmed directly from real save-route code.

Confirmed — YCW NOS criteria (session-status-260720.md, marker-save integration (2026-07-21).md):

PrefixMeaningNotes
NQ1, NQ2, ...YW-course ratingScores 13; 0 = not-assessed (seed default)
NC1, NC2, ...YW-course commentOptional
QQ1, QQ2, ...SP-course ratingRenamed from SQ/SC to avoid colliding with the real Supervisor prefix
QC1, QC2, ...SP-course commentOptional
  • Write to two destinations, both confirmed as of 2026-07-25: staffJSON.marker on the ST record itself (so the survey form correctly re-populates these fields on reload), and a separate table (NOScriteria, one row per student, keyed by studentID) — extracted inline during marker-save, non-fatally (a NOScriteria write failure never blocks the actual marker save). Originally documented (2026-07-21) as writing to NOScriteria only — corrected once the staffJSON.marker round-trip gap was found.
  • Fix history — this took three attempts across two sessions to actually land, not one: extractMarkerData() in TaskClient.tsx originally (client-side) only forwarded MQ* + markerID, silently stripping NQ*/QQ*/NC*/QC* before they ever reached the server — identified 2026-07-21, but the fix wasn't actually deployed, confirmed by a live test on 2026-07-25 that still showed the gap. That same test-and-trace also found the identical bug in two further, previously-undocumented locations: marker-save/route.ts's own markerAnswers filter (server-side write), and [rowId]/route.ts's extractStaffSections() fallback filter (server-side read-back) — both also only kept MQ*. All three are now fixed with the same widened five-prefix list, confirmed via a real save → reload round-trip. Full account: marker-save-integration-2026-07-21.md's 2026-07-25 session update.
  • Open: NOScriteria's student-key field name is assumed studentID, not independently confirmed.

Reserved (this session):

PrefixMeaningNotes
MQL (exact)Never a visible questionMarker-only. Presence triggers the auto-loading Inspera score panel — see the MQL playbook. Not a "role-owned answer," a pure trigger/carrier

3. Upload prefixes and their companions

Confirmed, live in TaskClient.tsx's UploadKind union — type fixed by prefix at survey-authoring time, discovered via s.getAllQuestions()

  • regex match on type === "text", then q.visible = false to hide the built-in widget in favour of custom upload UI:
PrefixKindPipelineStatus
UL1, UL2, ...Main documentExtraction service (/extract/direct)Confirmed. Was .docx, now PDF (2026-07-23 decision)
FL1, FL2, ...Supporting fileSame extraction pipeline as UL*Confirmed, always PDF
PL1, PL2, ...PDF, stored onlyNo extractionPresent in code's upload-kind map; backend implementation status not independently verified in this index
AL1, AL2, ... (bare AL = instance 1)AudioNot implementedPlaceholder only — no pipeline decided. Paired C{n} content field is reserved for its future transcript, see note below
ML1, ML2, ...Images, multi-fileContact-sheet endpoint, own component (MultiImageUpload)Confirmed, but see caveat below
  • ML's trailing digit means something different from every other kind: for UL/FL/AL/PL the digit is an instance number (UL1, UL2 = two separate questions). For ML, the digit is the max files allowed (ML5 = one question, cap of 5 files) — confirmed safe only because there's ever one ML question per survey; a second ML question would break this reinterpretation.
  • DL (pptx) is aspirational, not implemented — mentioned only in a code comment as a future kind "extracted like UL." It is not in the actual UploadKind type union and has no entry in the style map. Don't confuse this with DL0* below — same two letters, unrelated purpose.
  • Content field C{n} — now vestigial, not actively used. Reserved for future use, tied to AL*. Each upload question X{n} still pairs with a hidden content field C{n} (e.g. UL1C1) in the code (contentFieldName), and C\d+ still appears in the server-side save/submit allow-lists. But its original purpose — carrying extracted text inline — was already skipped for docx/pdf/pptx uploads even before this session (SKIP_CONTENT_FIELD_TYPES in TaskClient.tsx), with extracted text living on TaskDocuments.extractedText server-side instead. Now that UL*/FL*/PL* are all PDF-only (2026-07-23 decision), every currently-implemented document upload kind falls into that skip list — there's no remaining upload type that actually populates C{n} today. Its only remaining live purpose is paired with AL* (audio, still Placeholder — no pipeline decided) — a future audio transcript is the one case left where C{n} would actually get written to again. Left in place structurally (field mapping, allow-list entries) for exactly that reason, not dead code to remove.

Video — confirmed, separate from the document pipeline entirely:

PrefixMeaning
VL1, VL2, ...Video upload — Bunny.net TUS, async move to S3-compatible storage. Fields live directly on the ST record (videoID, videoStatus, videoEmbedUrl, videoFilename, unsuffixed for VL1; video2ID etc. for VL2+, not confirmed, only inferred by analogy)
V1 (exact, type: "html")Companion display link for VL1's result — HTML interpolates {videoURL}. Visibility: visibleIf: "{videoURL} notempty", testing the field, not V1's own value
A1Stub — same companion-display role anticipated for future AL* audio, mirroring V1. Placeholder only

| Prefix | Meaning | Status | | --- | --- | --- ß| | DL01, DL02, ... | Static download link for a template file the student downloads and re-uploads (paired with a UL*), hardcoded at survey-authoring time | Confirmed convention. Not every UL*/VL* question needs a paired DL0* — plain evidence-upload tasks can have none | | WL1 | Dynamic download link for the renamed uploaded filename | visibleIf: "{XX1} notempty"no role restriction, visible to everyone. Populated server-side after the FTP-renamed-file save completes, independent of the survey's own save cycle | | LL1, LL2, LL3, LL4, ... | Resolvable view/download links for already-uploaded files (video, main file, supporting files, future audio), for supervisor + marker | Designed, not built. See the MQL playbook §8 for full detail. Visibility: "{superID} notempty} or {markerID} notempty" (author-controlled plain visibleIf, not code-enforced like MQ*). Resolves via its own filesID key (LL1:<uid>), reverse-direction of UL1's uid — points at a read-facing lookup, not a patch target. Still open: which record/table the filename/URL actually lives on |


5. Special-purpose / non-prefix carriers

FieldMeaningStatus
XX1Hidden carrier — never written back from the survey form itself; written server-side by the upload/video pipeline right after the FTP-renamed-file save completes. Lives in staffJSON.all — a third sub-key alongside super/marker, for content owned by no single role's save action, survives student/supervisor/marker saves automatically via existing pass-through/allow-list logicConfirmed
R1Whole-task resubmission — single question holding the prior task's student answers + marker feedback, condensed into one plain-text entry (not a per-question mirror). Excluded from aggregatedLog so it isn't double-countedConfirmed, scope currently believed Flow-B-specific, not yet confirmed general

6. Role editability — generic rule (this session)

Applies across Q*/SQ*/MQ*, code-enforced, ignoring whatever the survey JSON's own visibleIf/readOnly says:

PrefixOwning roleEveryone else
Q<n>studentreadOnly
SQ<n>supervisorreadOnly
MQ<n>markerreadOnly
(no prefix)observer and the future tutor role — always readOnly, on everything
  • tutor doesn't exist as a role yet in TaskClient.tsx (student / supervisor / marker / observer only). It's planned as a broader version of observer — its own tutor-to-student relationship model will define which students/placements it can see, replacing the placement > supervisor flag observer uses today. That model is deferred; the only settled behaviour is that tutor, once it exists, never edits anything, same as observer.
  • This is client-side defense in depth, not the real security boundary — the server-side allow-lists in save/route.ts/ submit/route.ts (Q*/UL\d+/C\d+ only) are what actually stop a role from persisting a value it shouldn't.

7. Open items across this whole index

  • observer's own question-visibility convention — never defined; only the hidden observer field exists.
  • PL*'s backend implementation status — present in the upload-kind code, not independently confirmed as a live server-side pipeline.
  • DL (pptx upload) — comment-only, not a real implemented kind.
  • VL2+'s field-suffix convention (video2ID etc.) — inferred by analogy, never directly confirmed.
  • NOScriteria's student-key field name — assumed studentID.
  • LLn — filename/URL storage location entirely undecided; see the MQL playbook §8 for the current state of that design.