Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
849 changes: 849 additions & 0 deletions docs/FILE-A01-safe-upload-policy-matrix.md

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions docs/english-only-submission-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# English-Only Assessment Submission Notice

## Proposed Notice

All assessment submissions must be written and submitted in English. Translation tools may be used to help understand the assessment instructions, but the final submitted work must remain in English.

## Recommended Placement

The notice should appear in the following locations:

1. **Assessment task details page** — near the assessment requirements.
2. **Submission upload page** — above the upload or submit button.
3. **Final submission confirmation window** — before the student confirms the submission.

## Behaviour When Translation Is Enabled

The notice should remain visible in English when the language or translation option is active. Translation must not hide or change the requirement that the final assessment submission must be in English.

## Scope

This document provides the proposed wording and recommended placement only. No application or interface changes have been implemented.
114 changes: 114 additions & 0 deletions docs/safe-upload-and-chat-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Task uploads and chat attachments

This guide covers the companion Safe Uploads changes under review. They become
available after the web and API PRs are reviewed and merged. It builds on
FILE-A01 by Sandil Sithmaka Bandara Weganthale and the existing FILE-F01 upload
requirements component. The earlier design matrix remains a design record;
this guide records the implemented boundaries and corrects audit assumptions.

## Students and staff

Before choosing a task submission, read its required categories, exact formats,
file count and size limit. Expand the list for Code. Provide one file for each
configured requirement. Spreadsheet means CSV, XLS or XLSX and keeps the original
file and all worksheets for download. The PDF contains a download notice. Code
uses the existing curated extension list; rename tricks do not bypass checks.
The task's PDF category means PDF. PostScript was advertised by the browser but
rejected by the API, so it is no longer advertised as accepted.

In task chat, requirements appear above the composer before selection. Use
**Attach a file** or drop a file onto the discussion. The server supplies the
exact formats. Document accepts DOCX; Spreadsheet accepts CSV or XLSX. Images,
PDF and supported audio remain available. Each attachment must be smaller than
30 MB (30,000,000 bytes), and you may select up to five at once.

Review the name, category and size, then **Post Attachment**. **Cancel** removes
that selection and leaves written text unchanged. Each file is posted as its
own comment. Your written draft is separate: use Send when ready to post it.
Uploading status appears while requests are pending. A failure keeps the draft;
choose the file again to retry. Policy errors explain why the server refused it.
A proxy size rejection asks you to use a smaller file.

Paste a screenshot while typing to enter the same image confirmation flow.
Only approved raster images are accepted from the clipboard. Ordinary text paste
still works. Duplicate paste/beforeinput browser events produce one confirmation.

Documents and spreadsheets appear as download cards with the filename and size.
**Download** uses the authenticated task endpoint. Office documents are never
rendered as active content in OnTrack. Existing attachments remain accessible to
authorized users. A removed or unavailable file produces an error, not access to
another task's file.

| Message / situation | Action |
| -------------------------------------- | ------------------------------------------------------------------------------- |
| Requirements unavailable | Reload and try again; text comments still work |
| Unsupported format | Save in one of the formats listed before selection |
| Empty file | Open and save the file again; check it contains data |
| File too large | Reduce size below the displayed limit |
| Malformed, encrypted or active content | Remove password protection/macros/embedded objects; export a clean copy |
| Legacy XLS in chat | Save as CSV or macro-free XLSX; task Spreadsheet requirements still accept XLS |
| Permission or missing-file error | Check the current task and contact teaching staff if access should be available |

## Unit chairs

In the task editor's upload requirements, choose a category rather than entering
extensions: PDF, Code, Image, Spreadsheet or Archive. Spreadsheet stores the
stable `csv` identifier and displays CSV/XLS/XLSX to students. Existing `archive`
values retain their meaning. No saved-task migration is needed.

The previous audit found a browser CSV/XLS/XLSX list and assumed the task pipeline
already supported it. The API actually omitted `csv` from category validation
and archive handling. The companion API PR completes these paths. It retains
spreadsheet originals and does not silently convert a workbook to its first sheet.

## Contributors and reviewers

- API authority: `app/helpers/comment_attachment_policy.rb`,
`spreadsheet_upload_policy.rb`, `file_helper.rb`, and `task_comments_api.rb`.
- Browser policy interface: `src/app/api/models/task-comment/attachment-policy.ts`.
- Composer owns picker, drop and clipboard confirmation. The viewer delegates
drops to that flow so there is no second permissive allowlist.
- `file-upload-types.ts` owns task browser categories; `upload-category.ts`
supplies requirement labels. The unit-chair selector uses the same stable keys.
- API validates bytes independently; browser MIME is not trusted. Office files
undergo ZIP/XML, active-content and external-content checks and remain download-only.
- Task size: configured API limit, 10,000,000-byte fallback, inclusive. Chat size:
strictly below 30,000,000 bytes. The production proxy default remains 1g; see
[deploy PR 37](https://github.com/ontrack-features-t2-2026/doubtfire-deploy/pull/37)
for finite-limit validation, JSON 413 and real API boundary probe commands.

To change a format, first update and review the API policy and validators. Add
success, renamed-content, malformed, size, authorization and safe-download tests.
The browser automatically receives chat picker extensions. For task categories,
update both the API and browser contract and verify original archive retention.
Do not add arbitrary unit-chair extension entry. New formats need a teaching use
case and a security decision; a browser MIME string is not that decision.

Run with the repository's supported Node version (22.22.3 or newer):

```sh
npm run test:ci -- --include='src/app/tasks/task-comment-composer/**/*.spec.ts' --include='src/app/tasks/task-comments-viewer/task-comments-viewer.component.spec.ts' --include='src/app/tasks/modals/upload-submission-modal/task-upload-requirements/*.spec.ts' --include='src/app/api/services/spec/task-comment.service.spec.ts'
npm run typecheck
npm run lint
npm run build -- --configuration development
```

The API regression matrix is in its `docs/uploads/safe-upload-contract.md`.
Tests cover clipboard duplication separately from file selection, failure draft
preservation, exclusion/size/count checks, drag/drop delegation and requirements.
API tests cover upload/download policy, cleanup, safe headers and access denial.

Repeat these browser checks at desktop and a narrow mobile width before release:

1. Create a Spreadsheet requirement and confirm CSV/XLS/XLSX in student guidance.
2. Select, drop and paste an image; confirm exactly once and cancel without losing text.
3. Select DOCX, CSV and XLSX, post, and download from an authorized account.
4. Try excluded, empty and oversize files; verify clear feedback and unchanged draft.
5. Tab through Attach, confirmation Cancel/Post and Download; verify visible focus,
accessible names and readable requirements at 200% zoom and narrow width.
6. Confirm images/audio/PDF and text-only comments retain their existing behavior.

No malware scanning, cloud-drive links, active Office preview, chat XLS, macro
files, encrypted packages, executables or arbitrary archives are added. Existing
FILE-S01 follow-ups about aggregate quotas and worker recovery remain explicit.
Non-GitHub evidence collection, leadership approval and merging are outside this PR.
118 changes: 118 additions & 0 deletions docs/submission-lifecycle/SLR-E01-policy-proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# SLR-E01: proposed post-feedback deadline rule

**Status: Proposed; awaiting stakeholder approval.** This is a decision input, not
approved policy, an implementation specification, or evidence that SLR-E01 is complete.
Merging this document does not authorise changes to student deadlines.

This readable version preserves the proposal contributed by ReneeSleepy in
[web #248](https://github.com/ontrack-features-t2-2026/doubtfire-web/pull/248).
The [original PDF](https://github.com/ontrack-features-t2-2026/doubtfire-web/blob/53f6d11340eba4d53e245184507ff3f91743761b/SLR-E01%20.pdf)
remains in that commit for provenance. It ended partway through its acceptance list;
the complete candidate checks and unresolved decisions are recorded below.

## Existing implementation and duplication check

The API already implements a resubmission extension. Reuse its named methods and
[existing rule record](https://github.com/ontrack-features-t2-2026/doubtfire-api/blob/bb360dfa/docs/submission-lifecycle/effective-resubmission-deadline.md)
before considering new work. This was checked against API `11.0.x` at `bb360dfa`
on 20 September 2026; API #94 is already included in that history.

| Area | Existing API behavior | Original proposal below |
| ------------------ | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| Eligible statuses | Fix and Resubmit, Discuss, Rediscuss, Demonstrate | Same four statuses |
| Eligibility window | Effective deadline less than seven calendar days after assessment | Every eligible feedback event, without that window |
| New date | Adds configured `extension_weeks_on_resubmit_request` to the existing deadline, subject to limits | Seven calendar days after feedback was recorded |
| Repeat handling | Guard targets one extension per submission round; known concurrency gaps remain | Each new eligible feedback event may recalculate |
| Flexible dates | Excluded by existing extension eligibility | Proposed to participate |
| Time zone | Student campus zone, falling back to application zone; effective deadline uses end-of-day anywhere on earth | Described only as the task/unit system time zone |
| Configuration | Unit-level extension configuration | Proposed task-level opt-out, enabled by default |

These are material policy differences, not missing frontend features. The existing
API record also identifies concurrency, transaction and group-comment risks; this
document does not claim to fix them. No API, web behavior, mobile behavior, deploy
configuration, migration or notification delivery changes are included here.

## Original proposed rule

When feedback is recorded with **Fix and Resubmit**, **Discuss**, **Rediscuss**, or
**Demonstrate**, calculate a candidate deadline seven calendar days after the
recorded feedback timestamp. Do not calculate the candidate by adding seven days
to the old deadline or by adding a fixed 168 hours.

The author's proposed interactions are:

- Preserve any later approved extension rather than reducing it.
- Include tasks with flexible dates.
- Respect final and maximum dates; an authorised exception to a final deadline
requires explicit approval.
- Recalculate for each genuinely new eligible feedback event, including another
event before the current extended deadline.
- Apply a consistent result to the relevant group submission and its member tasks.
- Enable the behavior for existing and new tasks, with an opt-out available to
authorised staff at task level.
- Apply only to future eligible feedback. Neither deployment, setting changes nor
old feedback should automatically rewrite historical deadlines.
- Preserve manually authorised changes and explain the actual resulting deadline
to the student, including any limiting final/maximum date.

The original suggested message was: "Your task deadline has been extended to
[date and time] because you received feedback requiring further action."
It is suitable only when the deadline actually moves later. Wording for no change,
a cap, or an opt-out needs acceptance alongside the final rule.

## Decisions required before implementation

| Decision | Why it remains open |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Deadline precedence | Early feedback plus seven days may be earlier than the original deadline. Decide explicitly whether the original deadline, a manual deadline, an approved extension, and an automatic date may ever be shortened. A possible no-shortening rule is a proposal, not an approved formula. |
| Conflicting caps | A later approved extension can exceed a stated final/maximum date. Decide which authority wins and what exception record is required; do not silently truncate an approved extension. |
| Authoritative time zone | Choose campus, unit or another named IANA zone and a fallback. Define whether the result is a wall-clock instant or an end-of-day date; current API semantics must not be changed implicitly. |
| DST transitions | Define the handling of nonexistent or repeated local times, in addition to using calendar days. Include forward and backward clock changes in tests. |
| Feedback identity | Define a genuinely new event versus a retry, re-save, repeated status change, or resubmission round. Decide whether the current one-extension-per-round rule changes. Duplicate delivery must remain idempotent. |
| Flexible and group tasks | Confirm the flexible-date change and how per-member deadlines, campus zones and manual extensions interact for groups. |
| Settings and rollout | Confirm default-on behavior, staff permissions, unit-level configuration interaction, effective start time and treatment of existing extension records. |
| Communication | Decide the authoritative API fields and whether the explanation is a discussion entry, in-app notice, push/email, or a combination. A visible message does not prove notification delivery. |

No stakeholder approval was supplied with this PR. The authorised policy owner
must record their name/role, decision date, chosen rules, rationale and approval
reference before SLR-E02 to SLR-E05 can treat this as an accepted contract.

## Worked examples from the proposal

All dates below illustrate the proposed local-calendar calculation. The zone and
deadline precedence still require the decisions above; these are not assertions
about current API output.

| Case | Input | Proposed candidate / result |
| -------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Normal | Original 20 Sep 2026 17:00; Fix and Resubmit recorded 15 Sep 14:00 | 22 Sep 14:00, before applying any authorised caps |
| Feedback after original deadline | Original 15 Sep 17:00; Discuss recorded 16 Sep 10:00 | 23 Sep 10:00, before caps |
| New feedback event | First feedback 10 Sep 09:00; next eligible event 14 Sep 15:00 | Candidates 17 Sep 09:00 then 21 Sep 15:00; a replay of either event is not a new event |
| Approved extension | Approved extension dated 25 Sep; feedback 18 Sep 10:00 | Candidate 25 Sep 10:00; the approved extension's exact time/zone is missing, so the later value cannot be selected yet |
| Task opt-out | Setting disabled; feedback 18 Sep 10:00 | No automatic deadline change under the proposal |

Add an early-feedback example (original 30 September, feedback 15 September,
candidate 22 September) to the policy decision: blindly replacing the original
would shorten the available time by eight days.

## Candidate acceptance checks after policy approval

- Each eligible outcome follows the accepted formula; ineligible outcomes do not
change the deadline.
- Early, on-time and late feedback follow the explicit precedence rules.
- Later approved/manual deadlines and final/maximum caps follow the recorded
authority decision, including a conflict between a later extension and a cap.
- A genuinely new event follows the repeat policy; retries, duplicate delivery,
concurrent assessments and failed transactions do not stack extensions.
- Spring/autumn DST, missing time zones, and cross-zone group members produce the
agreed date and offset; seven calendar days are not assumed to be 168 hours.
- Flexible dates, group propagation, unit settings and task opt-out follow the
accepted configuration and permission rules.
- Deployment and configuration changes leave historical feedback/deadlines intact
unless a separately approved migration explicitly says otherwise.
- Desktop web and the installed mobile PWA show the same server result, including
a readable date/time/zone, accessible feedback explanation, and any cap/no-change
wording. Do not recalculate the policy separately in each client.

Use synthetic accounts and dates for evidence. Link the exact API/web/deploy
revisions and test results after implementation; none are claimed by this proposal.
Loading