Update architecture baseline for sync, sharing, and gateways
This commit is contained in:
parent
9e01df5d64
commit
099c53badf
7 changed files with 200 additions and 102 deletions
45
docs/adr/0008-sync-capable-server-contract.md
Normal file
45
docs/adr/0008-sync-capable-server-contract.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# ADR-0008: Sync-capable server contract
|
||||
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
The desktop client is deferred, but the stable-v1 API must support a client that maintains a local replica without missing concurrent mutations or silently overwriting a newer revision. The previous plan named a change feed and one-way mirror but did not define a consistent initial baseline, delivery semantics, mutation attribution, or the difference between content and metadata changes.
|
||||
|
||||
## Decision
|
||||
|
||||
Drive's REST API and application services are the canonical server interface. The server exposes neutral read, mutation, transfer, and change primitives; sync direction, deletion propagation, local filesystem policy, and three-way reconciliation remain client concerns.
|
||||
|
||||
### Baseline and changes
|
||||
|
||||
1. A client obtains opaque start cursor `C0`.
|
||||
2. It recursively enumerates a selected root using stable node and parent IDs with keyset pagination.
|
||||
3. It replays changes after `C0` until caught up.
|
||||
4. It persists the cursor after the final event it has applied.
|
||||
|
||||
Enumeration and replay may contain duplicate observations but must not miss a committed mutation while the start cursor remains retained. No long-running PostgreSQL snapshot is held.
|
||||
|
||||
The change feed is ordered by a monotonic sequence and consumers treat delivery as at least once. A page cursor represents the position after its final event. Each versioned event stores either an immutable resulting-node snapshot or a deletion tombstone, node and content revisions, subtree effect, origin information, and useful previous-location diagnostics. Cursor expiry returns `410 Gone` with stable code `change_cursor_expired` and requires rebaseline without discarding pending local work.
|
||||
|
||||
Subtree-scoped credentials consume an authorization-safe projection of the global sequence. A move into the granted root is represented by current state, a move out is represented as a tombstone/removal, and unrelated events are omitted while the cursor advances. Recursive baseline and replay use the same root anchor and visibility rules, so a restricted client can maintain its authorized replica without learning metadata outside it.
|
||||
|
||||
### Identity, revisions, and idempotency
|
||||
|
||||
- Node revision increments for any meaningful mutation. Content revision increments only when committed file content changes.
|
||||
- SHA-256 identifies committed content. Logical `content_modified_at` may preserve an authenticated client value; server `metadata_updated_at` records the latest mutation. Timestamps never decide conflicts.
|
||||
- Authenticated client instances may bind to API tokens and are independently revocable. Application services receive a protocol-neutral mutation context for actor, credential, client, operation, idempotency, and request IDs.
|
||||
- Idempotency records persist the authenticated scope, key, request fingerprint, operation, state, result reference, and expiry. Identical retries return the original result; a different fingerprint with the same key fails.
|
||||
|
||||
### Capabilities and transfers
|
||||
|
||||
`GET /api/v1/capabilities` reports protocol compatibility and supported behavior rather than requiring consumers to infer it from a software version.
|
||||
|
||||
Upload creation may accept declared size, SHA-256, logical content mtime, target/precondition, and origin. After authorization, the server may avoid transfer or attach an already verified owner blob through the normal commit service. New content is always server-hashed and verified.
|
||||
|
||||
Hash preflight is target-scoped and must not reveal whether matching content exists outside the credential's authorized view. The server may conceal whether internal deduplication occurred.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Phase 1 owns the supporting schema and mutation context; Phase 2 owns the functional baseline, changes, capabilities, and conformance mirror.
|
||||
- Web, importer, OnlyOffice, future desktop/rclone clients, and protocol gateways produce attributed events through the same application services.
|
||||
- Client sync modes, SQLite schema, watcher behavior, local conflict copies, and provider adapters are deliberately deferred to the desktop-client design.
|
||||
25
docs/adr/0009-external-protocol-gateway-boundary.md
Normal file
25
docs/adr/0009-external-protocol-gateway-boundary.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# ADR-0009: External protocol gateway boundary
|
||||
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Existing backup and automation tools may benefit from WebDAV or rclone compatibility. Managed Drive storage is not a user-visible filesystem: PostgreSQL owns hierarchy and revisions while the array contains opaque immutable blobs. Direct protocol access to object paths would bypass authorization, commit intents, change events, trash, replacement recovery, and audit.
|
||||
|
||||
## Decision
|
||||
|
||||
- REST and application services remain canonical.
|
||||
- A writable WebDAV gateway MAY be implemented post-v1 as a protocol translator. Every write calls normal application services, uses revision preconditions, creates normal audit/change records, and sends deletion to trash unless a credential explicitly permits permanent deletion.
|
||||
- WebDAV uses independently revocable, action- and subtree-scoped credentials. Durable WebDAV lock tables are added with that module, not pre-created in the core schema.
|
||||
- A native rclone backend MAY later call the REST API directly for richer hashes, modification times, resumable uploads, server-side move/copy, trash, and error semantics. Generic rclone-over-WebDAV and a native backend may coexist.
|
||||
- Native rsync service, rsync staging ingestion, and direct SMB/SFTP access to managed object storage are not planned. Rsync may operate on a local folder maintained by a future desktop client, never on Drive's server object directory.
|
||||
- No gateway may import storage adapters or mutate core repository tables directly (I16).
|
||||
|
||||
Integration configuration and lock tables are introduced only when their module is implemented. Phase 1 adds only the shared foundations already required by REST clients: client identity, persistent idempotency, mutation attribution, and scoped credentials.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Future compatibility does not force writable WebDAV or integration-specific tables into stable v1.
|
||||
- Existing tools can gain interoperability later without weakening the immutable object model.
|
||||
- A protocol gateway must provide streaming, conditional requests, bounded listings, authentication, audit, and revocation appropriate to that protocol.
|
||||
|
||||
|
|
@ -11,4 +11,5 @@ ADRs are immutable after acceptance. Supersede an earlier decision with a new AD
|
|||
| 0005 | HTTP precondition and conflict status codes | Accepted |
|
||||
| 0006 | Stable-v1 and deferred product scope | Accepted |
|
||||
| 0007 | Open first-run setup | Accepted risk |
|
||||
|
||||
| 0008 | Sync-capable server contract | Accepted |
|
||||
| 0009 | External protocol gateway boundary | Accepted |
|
||||
|
|
|
|||
|
|
@ -16,9 +16,18 @@ Transport code handles protocol concerns only. Application services own transact
|
|||
|
||||
No authoritative state lives only in memory. Upload sessions, commit intents, jobs, leases, and cursors are persisted in PostgreSQL. Committed blobs are immutable and become visible only after storage promotion and metadata commit.
|
||||
|
||||
## Sync-ready server contract
|
||||
|
||||
The server exposes neutral file and change primitives, not client sync modes. A consumer obtains a start cursor, recursively enumerates stable node/parent IDs, then replays the durable change feed until caught up. Events carry resulting state or tombstones and are safe to process more than once. See ADR-0008.
|
||||
|
||||
Node revision covers all meaningful mutations; content revision and SHA-256 distinguish content changes from rename, move, favorite, or trash metadata changes. Persistent idempotency and authenticated client attribution apply to every transport.
|
||||
|
||||
## External protocols
|
||||
|
||||
REST and application services are canonical. A future WebDAV gateway translates protocol requests into those services, and a native rclone backend may consume REST directly. Neither may touch managed object storage or repository tables. Rsync server access is not planned. See ADR-0009.
|
||||
|
||||
## Frontend
|
||||
|
||||
Each feature owns its routes, API hooks, components, state, and tests. Cross-feature access goes through a small public entrypoint. Server state stays in TanStack Query and local UI state remains close to the component or feature that owns it.
|
||||
|
||||
Preview rendering is capability-driven and lazy-loaded. Adding a format must not require editing the file manager.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
- Drive to the existing OnlyOffice Document Server.
|
||||
- Public-link visitors to explicitly shared resources.
|
||||
- Read-only importer mounts to managed Drive storage.
|
||||
- Future WebDAV/rclone credentials to an explicitly granted Drive subtree and action set.
|
||||
|
||||
## Primary threats
|
||||
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
- Session theft, CSRF, credential guessing, token leakage, and proxy-address spoofing.
|
||||
- Path traversal, symlink following, MIME confusion, malicious previews, and archive expansion.
|
||||
- SSRF or forged OnlyOffice callbacks.
|
||||
- Over-broad, leaked, or revoked integration credentials and protocol gateways that bypass application services.
|
||||
- Stale writes, duplicate requests, interrupted commits, and premature GC.
|
||||
- Secret disclosure through logs, images, configuration, backups, or repository history.
|
||||
|
||||
|
|
@ -31,6 +33,6 @@
|
|||
- Non-root container, explicit mounts, private PostgreSQL network, and health endpoints.
|
||||
- Architectural boundaries prevent HTTP code from reaching database or managed storage directly.
|
||||
- Security headers, CSRF, authentication, rate limits, scoped tokens, and callback validation are implemented with their Phase 1 features.
|
||||
- Phase 1 credentials are independently revocable and may be restricted by subtree and action; future gateways must use them and the canonical mutation path.
|
||||
|
||||
Review this document whenever a new external integration, public endpoint, preview processor, or authentication mechanism is introduced.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue