Skip to main content

Upload Token System

Upload Token System

Upload Token System

This is the authoritative reference for the generic public upload-token product implemented in skyhawk_site_fixes.

Architecture

  • Public route: /upload/{token}.
  • Admin route: /admin/skyhawk/upload-tokens.
  • The public route is owned by UploadTokenForm.
  • Drupal core managed_file owns file selection, AJAX transfer, validation, and temporary file entities.
  • Files are stored under private://uploads/[token]/.
  • No custom synthetic mouse event or parallel direct-upload controller participates in the live product.

Public Upload Page Workflow

  • The public page has no redundant generic Upload page title. Its identifying heading is Upload Files: [label].
  • The secret token value is never displayed.
  • Selecting files is the upload action. Drupal core managed_file immediately starts AJAX transfer from the file-input change event.
  • Successful initial uploads become temporary Drupal managed files under private://uploads/[token]/.
  • The final action is Finish submission.
  • Skyhawk custom-form results never use Drupal messenger/status popups. Upload/finalization results render inline on the form using the established PageMessageTrait pattern required by Tier-1 Rule 8.3.

Token Lifecycle

  • A token is valid when it exists, has status active, and has not expired.
  • Generated tokens have a minimum lifetime of seven days.
  • A token may be used for multiple upload sessions until expiry or explicit administrative revocation.
  • A successful upload does not consume or invalidate the token.
  • uses_count records cumulative finalized files for administrative information only.
  • uses_allowed = 0 is retained as the unlimited-until-expiry/revocation sentinel for schema compatibility.

Upload Rules

  • Multiple files may be selected.
  • Maximum individual file size is 511 MiB (535,822,336 bytes).
  • The hosting transport ceiling remains 512 MiB for an HTTP POST, so exceptionally large batches may need to be selected/uploaded separately even though each individual file is legal.
  • After Drupal receives temporary managed files, final submission makes them permanent, records each file in skyhawk_upload_file, increments cumulative file accounting, and sends the configured batch notification.
  • Completion notifications contain only the files finalized in that batch, not every historical file associated with the token.

Administration

  • The admin form creates reusable tokens and sends the upload URL by email.
  • The admin form can explicitly revoke an active token.
  • Existing contact and purpose data are reused.
  • The current history table remains operational; conversion to a Drupal View is a later Views-first improvement, not part of the uploader replacement.

Replacement State

The public and admin upload forms were replaced in toto after a discovery audit found contradictory one-use lifecycle logic, a redundant unrouted direct-upload controller, and a custom mobile workaround that duplicated Drupal core behavior.

The old UploadTokenController and upload_token_mobile_fix.js are retired into the timestamped replacement backup rather than destroyed during initial acceptance testing.

Functional acceptance remains pending until the Pixel test verifies: legal multi-file upload, final submission, private storage, history rows, notification, reuse of the same token, explicit revocation, expiry rejection, and oversize rejection.

Current Functional State

Generic initial upload: ACCEPTED. Drupal core managed_file owns selection and AJAX transfer to temporary token-scoped private storage. Format-specific diagnosis is closed.

Finish submission: functionally proven. A Pixel test completed Finish submission, returned the form to an empty file field for another batch, and produced a permanent token-scoped managed file. C5 remains active.

Public-page UX server correction applied and verified: the /upload/{token} route no longer owns the redundant generic Upload title. UploadTokenForm no longer uses its successful-upload Drupal messenger popup. The established PageMessageTrait setter and inline renderer are installed. Pixel/Chrome confirmation of these two presentation changes is the next required functional gate before this UX correction is accepted.

Current evidence boundary: refresh the existing C5 public page and verify the generic Upload title is absent. Then complete one ordinary batch and verify the result appears inline with no Drupal Status message popup. Do not reopen generic upload or Finish-submission mechanics during this presentation gate.

Current Regression Token

No token label is permanently reserved as the regression token. Use a currently active, unexpired test token from the existing token system. Do not create a replacement token merely because an upload test fails.