oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

Native Sheets for Mac and iOS

Status: reviewed for implementation by independently dispatched gpt-6-astra (high), 2026-09-13. Spec-only approval; branch/parity validation remains required. User decisions, 2026-09-13: simultaneous Mac and iOS builds; full editing parity with the existing web app; entirely native editors. This extends the original design's deferred mobile-native row without changing the sealed-at-rest trust model or server calculation authority.

Actual parity inventory

Source baseline: internal/sheets/app.go, templates/sheet.html, templates/table.html, static/commands.js, static/clipboard.js, handlers_grid.go, handlers_history.go, handlers_comments.go, handlers_view.go.

| Existing working surface | Native implementation | | --- | --- | | Home sign-in, team/sheet grants | Shared RastrilloApple authentication, instance selection; existing server identity/actor/grants middleware | | Sheet list, create, rename | Native navigation list and forms over JSON responses | | One worksheet per document | Same first-tab identity; no invented tab creation | | Formula bar and editable cells | Native SwiftUI grid, selection and native text fields; server evaluates and formats every input | | Range selection, select all, clear, copy/cut/paste, fill down/right | Native range address field and clipboard; existing atomic batch route and server copy translation | | Insert Function: SUM/AVERAGE/COUNT/MIN/MAX | Native insert menu infers arguments with the same selection semantics as commands.js, then submits through the server calc path | | Keyboard Enter/Tab commit-and-navigate, Escape abandon, undo/format/copy/paste/select-all shortcuts | Native focus and keyboard actions, preserving unsaved drafts until confirmed | | Bold/italic/alignment/number format/fill/text colour/clear formatting | Native menus call existing range format endpoint; server style records remain canonical | | Row height/column width | Native numeric controls call existing size endpoint | | Input undo; cell history and restore | Native history panel; existing actor-specific undo and restore paths | | Non-destructive sort/filter in table view | Native view controls; server applyView returns source row coordinates, preserving reference and edit identity | | Cell comment threads and resolve | Native comment panel using existing sealed comment storage and commenter permission | | Owner grants/revocation/viewer-or-commenter share links | Native sharing panel with existing grant validation | | XLSX import and export | Native .xlsx/.xlsm file import and .xlsx export; same converter and jobs; first worksheet limitation clearly stated | | SSE edits, resync, reconnect | Existing stream with monotonically versioned server responses; cancel on navigation, refetch snapshot after reconnect/resync | | Light/dark choice and imported fill/ink warning | Native per-person preference; authored colours retained and warning surfaced |

Charts, conditional-format rule editing, multi-worksheet UI, row/column insertion/deletion, destructive sort, formatting/resize undo, and offline editing are not implemented in the current web product. They are not falsely represented as parity requirements met by new native controls. The initial native work must nevertheless cover every working surface above.

Architecture and safety

native/ contains a Swift package executable shared by macOS 26 and iOS 26, platform app metadata and repeatable build scripts based on Calendar/Memoria. RastrilloApple is pinned to 33ffe994173438bbb45e88d16061eba2ac4f6d4c. No WKWebView or JavaScript editor is used. Auth uses the shared system-browser flow. AppKit/UIKit use is limited to platform clipboard/file integration where SwiftUI does not expose the needed function.

Add JSON read adapters for list, sheet metadata, history, comments, sharing and ordered row windows. Existing command endpoints remain canonical; where their response is HTML, add explicit JSON response negotiation while preserving the HTML routes. A native request cannot bypass actor, sheetFromURL, openTab, mayWrite, mayComment or sharing ownership. Every SSE delivery must re-resolve current native token/session validity, current admission and sheet grants; the existing stream captures an actor at subscription and its mayRead check alone is insufficient for token revocation. Token invalidation closes the stream before delivering more content. All writes use existing store/calc and sealed persistence paths. API responses are Cache-Control: no-store; editing content lives only in memory, never an unsealed disk cache. An explicit user export streams to a private temporary XLSX for the system save picker; this export staging file is removed on completion, cancellation or failure and is not a document cache. Failed saves keep the input draft and show a retryable error. Navigation and closing must surface unresolved drafts with save/discard/cancel, and export waits for pending writes before reading server content. Import job ownership remains sessions.Current.Subject, not actor.ID; native JSON progress/result polling resolves that same session subject and never exposes another owner’s job.

The grid uses stable original coordinates as identity, virtualized rows, accessible cell labels, native selection and range-address controls, and explicit fill/resize menu alternatives. Snapshot refresh must not overwrite a focused unsaved draft. Writes are serialized; server versions older than the accepted version are ignored, gaps trigger refetch rather than invented local values. Full snapshot replacement clears deleted cells and old formats. Batch paste observes server byte/count caps and never silently truncates a paste. Server formula translation is used for internal copied cells including mixed/absolute references. Native sort/filter never moves storage coordinates.

Verification and completion

Server tests cover JSON access with independent members and roles, mutation permission refusal, native response negotiation, sorting coordinates, history/comment privacy, and unchanged sealed-at-rest gates. Swift tests cover coordinate parsing/ranges, TSV quoting, copy origins, insert-function selection semantics, select-all, keyboard commit/Tab/Enter/Escape and serial/version reconciliation. SSE tests revoke a native token and admission during an established stream and require no further content delivery. Build both actual macOS app and generic iOS Simulator app with Xcode. Exercise native rendering and editing against fixtures when simulator tooling permits; report any unavailable verification explicitly. Do not claim complete parity until the inventory is wired and exercised. Import tests cover .xlsx/.xlsm and cross-session job polling refusal. No publishing or deployment is authorized by this implementation task.