OpenSpec Change: enterprise-drive-sharing
- Change ID: enterprise-drive-sharing
- Package:
@suaveplan/drive-sharing
- Category: universal
- Target path:
packages/drive/drive-sharing
- Status: PROPOSED
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/drive-sharing.md
Summary
Deliver @suaveplan/drive-sharing on the genesis branch from scratch at enterprise quality. The enterprise spec describes it as "Partitioned drive with envelope encryption". The package provides partitioned drive management with per-partition policies, envelope encryption (key-wrapping via WebCrypto), a key ring for multi-user key management, sharing grants (access control), revocable share tokens, cross-partition file transfer, and typed branded ID utilities. Genesis adds structured errors via @suaveplan/error, Zod schemas for all public option types, OTel instrumentation, AbortSignal cancellation, injectable clock and RNG, property-based tests (fast-check), and a mitata benchmark suite. The @suaveplan/permissions package is not yet implemented on genesis; the permissions surface is inlined here (policy validation) and will be extracted when @suaveplan/permissions lands.
Gap analysis: sub-standard → enterprise
Security gaps
| Main-branch / prior art |
Genesis fix |
| Envelope encryption used AES-KW without AAD, permitting cut-and-paste attacks |
envelopeEncrypt requires AAD (partition ID + file ID) and fails open on missing AAD |
Key ring stored wrapped keys in a plain Map with no integrity checks |
KeyRing validates wrapped-key algorithm tags and checksums on getKey; corrupted entries throw SHARE_KEY_NOT_FOUND |
| No key rotation strategy — re-encryption required manual file-by-file traversal |
KeyRing.rotateKey re-wraps the user key; TransferManager propagates re-wrapped keys across partitions atomically |
| WebCrypto provider was hardcoded with no alternative |
CryptoProvider interface is injectable; WebCryptoProvider is the default but callers may substitute FIPS-validated or HSM-backed providers |
| Token and grant payloads carried plaintext user IDs and partition IDs without signing |
Share tokens include an integrity MAC computed via computeIntegrity; grants carry createdAt and expiresAt signed by the partition owner |
| No audit trail for grant creation or revocation |
EventBusLike emits grant:created, grant:revoked, key:rotated events with full context (no key material) |
Reliability gaps
| Main-branch / prior art |
Genesis fix |
| Token TTL was a hardcoded constant (24 h) with no override |
TokenManagerConfig.defaultTTL is configurable per instance; CreateTokenOptions.expiresIn overrides per token |
| Grant expiry had no clock injection, making time-based tests flaky |
TokenManager and PartitionManager accept injectable Clock; all expiry checks use clock.now() |
| Partition policy validation was ad-hoc boolean logic |
validateAction uses a deterministic state machine with exhaustive PolicyAction enumeration; Zod schemas prevent invalid policy shapes |
| Cross-partition transfer had no retry or atomicity guarantees |
TransferManager implements two-phase transfer (export → validate → import) with rollback on failure |
| Key ring import/export had no format versioning |
KeyRing.export produces versioned JSON (keyring_format_version: 1); import rejects unknown versions |
Observability gaps
| Main-branch / prior art |
Genesis fix |
| No per-partition metrics |
Counter share.partition.member_total per partition; histogram share.partition.policy_check_duration_ms |
| No span correlation across envelope encryption boundaries |
envelopeEncrypt / envelopeDecrypt create SpanKind.INTERNAL spans parented under the calling drive.read / drive.write span with encryption.algorithm attribute |
| No visibility into grant check denial reasons |
GrantCheckResult carries reason string; denied checks emit share.grant.denied_total counter with reason attribute |
| No structured logging for key-ring events |
KeyRing events (key:added, key:removed, key:rotated) are logged at info level with user_id and partition_id attributes |
Testability gaps
| Main-branch / prior art |
Genesis fix |
| No property-based tests for grant expiry |
fast-check invariant: for any TTL T and clock offset C, grantManager.check returns allowed: false when C > T |
| No property-based tests for token revocation finality |
fast-check invariant: once tokenManager.revoke(id) is called, validate(id).valid is always false for all subsequent calls |
| No determinism in policy merge tests |
Injectable Clock and deterministic mergePolicies enable reproducible property tests for non-conflicting field commutativity |
| No load-test criteria for 10K+ grant checks |
mitata benchmark grant_check_10k defines a regression gate (< 50 ms total) |
Operational gaps
| Main-branch / prior art |
Genesis fix |
| No preset tuning for partition policies |
DEFAULT_PRESETS (public, private, shared, encrypted) provide ready-made policies with documented security postures |
| No memory pressure handling during bulk key ring operations |
KeyRing operations stream over entries; export yields an array but caps at 10 000 entries with pagination metadata |
| No graceful degradation on partition store failure |
PartitionManager falls back to read-only mode when PartitionStore is unreachable; mutations return SHARE_POLICY_VIOLATION with retryable: true |
| No circuit breaker for crypto provider |
CryptoProvider operations time out after 5 s; repeated timeouts trigger read-only mode for encryption-dependent partitions |
Security model
Threat model
- Insider threat (partition member escalation) — A member with
read permission must not be able to elevate to write or admin without the partition owner's explicit grant.
- External threat (token theft or replay) — A stolen share token must be unusable after revocation or expiry; tokens must not be forgeable without the partition master key.
- Compromised key-ring storage — If the
PartitionStore or KeyRing backing store is compromised, the attacker gains only wrapped keys; plaintext data keys remain inside the Drive process boundary.
Encryption boundaries
- Plaintext lives only in the
Drive process memory during envelopeEncrypt / envelopeDecrypt and inside the TransferManager re-encryption buffer.
- Plaintext never lives in
PartitionStore, KeyRing exports, grant metadata, token storage, or logs.
- Wrapped keys (encrypted under the master key) are the only key material that crosses the process boundary into storage.
- Master key material is held only by
KeyRing and is never serialised or logged.
Key derivation hardening
- Envelope encryption keys are generated by the injectable
CryptoProvider (default: crypto.subtle.generateKey) with 256-bit entropy.
- Key-wrapping keys (KEKs) are derived from the partition master key via HKDF-SHA-256 with a context string that includes the partition ID and user ID, preventing cross-partition and cross-user key unwrapping.
- Master key rotation:
KeyRing.rotateKey generates a new master key, re-wraps all user keys, and emits a key:rotated event. Old master keys are zeroed from memory immediately after rotation.
Authenticated encryption
- AEAD modes: AES-256-GCM (default) or XChaCha20-Poly1305 (configurable via
EncryptionAlgorithm).
- Nonce management: 96-bit random nonces for GCM, 192-bit for XChaCha20-Poly1305, generated per
envelopeEncrypt call via the injectable Rng.
- AAD: Every envelope encryption includes
AAD = partitionId \|\| fileId to bind the ciphertext to a specific partition and file, preventing cut-and-paste across contexts.
- Tag verification: AEAD tag verification is constant-time; decryption failures throw
SHARE_ENCRYPTION_FAILED without revealing whether the ciphertext or the AAD was invalid.
Side-channel resistance
- Constant-time key comparison —
KeyRing.getKey comparisons and CryptoProvider unwrap validation use timing-safe equality.
- Timing-safe integrity verification —
verifyIntegrity uses constant-time comparison; no early return on mismatch.
- Memory clearing — Unwrapped data keys and master key buffers are overwritten with zeros after use (
Uint8Array.fill(0)) where the runtime permits.
Key rotation strategy
- User-level rotation:
KeyRing.rotateKey(userId, newKey) re-wraps the user's key under a new master key. The old wrapped key is replaced atomically.
- Partition-level rotation: When a partition master key is rotated, all member keys are re-wrapped in a single transaction.
TransferManager uses the new KEK for all subsequent cross-partition moves.
- Token invalidation on rotation: All active share tokens for a partition are revoked automatically when the partition master key is rotated, forcing re-authentication.
Performance SLOs
Latency budgets
| Operation |
p50 |
p99 |
Notes |
grantManager.check |
< 0.5 ms |
< 2 ms |
In-memory lookup, no IO |
tokenManager.validate |
< 0.5 ms |
< 2 ms |
In-memory lookup + HMAC verify |
keyRing.getKey |
< 1 ms |
< 5 ms |
Unwrap via WebCrypto |
envelopeEncrypt (1 MiB) |
< 10 ms |
< 50 ms |
AES-256-GCM via WebCrypto |
envelopeDecrypt (1 MiB) |
< 10 ms |
< 50 ms |
AES-256-GCM via WebCrypto |
transferManager.transfer (1 MiB) |
< 50 ms |
< 200 ms |
Export + re-encrypt + import |
partitionManager.create |
< 5 ms |
< 20 ms |
Policy validation + store write |
Throughput guarantees
- Grant checks: ≥ 100 000 checks/sec single-threaded (in-memory, no IO).
- Token validations: ≥ 100 000 validations/sec single-threaded.
- Envelope encryption throughput: ≥ 100 MiB/sec for 1 MiB–100 MiB files via WebCrypto (hardware-accelerated AES-GCM).
- Cross-partition transfer: ≥ 50 MiB/sec sustained for files 10 MiB–1 GiB, including re-encryption overhead.
Memory bounds
- Max resident memory during 1 GiB cross-partition transfer: ≤ 32 MiB (streaming 4 MiB blocks with bounded re-encryption buffers).
- Key ring: ≤ 1 KiB per entry (user ID + wrapped key metadata).
- Grant store: ≤ 512 bytes per grant.
- Token store: ≤ 256 bytes per token.
Chunk size optimization and dedup savings targets
- Not applicable to
@suaveplan/drive-sharing — chunking and dedup are handled by the underlying @suaveplan/drive package. Sharing operates on whole-file keys and metadata.
Scalability limits
| Resource |
Soft limit |
Hard limit |
| Max partitions |
100 000 |
1 000 000 |
| Max members per partition |
1 000 |
10 000 |
| Max grants active |
1 000 000 |
10 000 000 |
| Max tokens active |
1 000 000 |
10 000 000 |
| Max keys in key ring |
10 000 |
100 000 |
| Max concurrent transfers |
64 |
256 |
Observability plan
OTel spans
| Public operation |
Span name |
SpanKind |
Attributes |
partitionManager.create |
share.partition.create |
SERVER |
partition.id, partition.type, partition.owner_id |
partitionManager.addMember |
share.partition.add_member |
SERVER |
partition.id, user.id |
grantManager.create |
share.grant.create |
SERVER |
grant.id, grantor.id, grantee.id, partition.id |
grantManager.check |
share.grant.check |
INTERNAL |
grant.id, user.id, action, result |
tokenManager.create |
share.token.create |
SERVER |
token.id, partition.id, created_by |
tokenManager.validate |
share.token.validate |
INTERNAL |
token.id, valid, reason |
transferManager.transfer |
share.transfer |
SERVER |
file.id, source_partition, target_partition, direction |
keyRing.addKey |
share.key.add |
INTERNAL |
user.id, key.algorithm |
keyRing.rotateKey |
share.key.rotate |
INTERNAL |
user.id, partition.id |
envelopeEncrypt |
share.envelope.encrypt |
INTERNAL |
encryption.algorithm, aad.length |
envelopeDecrypt |
share.envelope.decrypt |
INTERNAL |
encryption.algorithm, aad.length |
Metrics
| Metric name |
Type |
Unit |
Description |
share.partition.create_total |
Counter |
1 |
Partitions created |
share.partition.member_total |
Counter |
1 |
Members added per partition |
share.grant.create_total |
Counter |
1 |
Grants created |
share.grant.check_total |
Counter |
1 |
Grant checks performed |
share.grant.denied_total |
Counter |
1 |
Denied grant checks |
share.token.create_total |
Counter |
1 |
Tokens created |
share.token.validate_total |
Counter |
1 |
Token validations performed |
share.token.revoked_total |
Counter |
1 |
Tokens revoked |
share.transfer.duration_ms |
Histogram |
ms |
Cross-partition transfer latency |
share.transfer.bytes_total |
Counter |
bytes |
Bytes transferred |
share.key.rotate_total |
Counter |
1 |
Key rotations performed |
share.envelope.duration_ms |
Histogram |
ms |
Envelope encrypt/decrypt latency |
share.policy.check_duration_ms |
Histogram |
ms |
Policy validation latency |
Structured logging
- All log lines are JSON with
timestamp, level, msg, trace_id, span_id, service.name (@suaveplan/drive-sharing).
- Sensitive fields (master keys, unwrapped data keys, wrapping keys) are redacted with
[REDACTED].
- Lifecycle events (
partition:created, key:rotated, grant:revoked) emitted via EventBusLike are also logged at info level.
Health checks
PartitionStore.health(): Promise<HealthStatus> — ping the backing store every 30 s.
KeyRing.health(): HealthStatus — validates that the master key is present and at least one crypto operation succeeds.
DriveShare.health(): HealthStatus — aggregates partition store health, key-ring health, and crypto provider readiness.
Alerting thresholds
| Alert |
Condition |
Severity |
| Grant denial spike |
share.grant.denied_total > 100 / min |
warning |
| Token validation failure rate |
share.token.validate_total with valid: false > 5 % |
warning |
| Transfer latency p99 |
share.transfer.duration_ms p99 > 500 ms |
warning |
| Key rotation failure |
SHARE_KEY_NOT_FOUND or SHARE_ENCRYPTION_FAILED during rotation |
critical |
| Partition store unavailable |
share.partition.create_total drops to zero with store errors |
critical |
| Crypto provider timeout |
share.envelope.duration_ms p99 > 5 s |
critical |
Dependency audit
Runtime dependencies
| Package |
Version constraint |
Justification |
Supply-chain risk |
Tree-shakeable |
License |
@suaveplan/drive |
workspace:^ |
Underlying virtual filesystem for partition storage |
Low (monorepo, same CI) |
Yes |
Proprietary |
@suaveplan/error |
workspace:^ |
Structured error base class and code registry |
Low (monorepo) |
Yes |
Proprietary |
@suaveplan/types |
workspace:^ |
Injectable Clock, Rng, LoggerLike, EventBusLike |
Low (monorepo) |
Yes |
Proprietary |
@suaveplan/crypto |
workspace:^ |
AEAD, sign, agree — envelope encryption primitives |
Low (monorepo) |
Yes |
Proprietary |
@suaveplan/crypto-keys |
workspace:^ |
KeyPair, Keychain — key ring key material management |
Low (monorepo) |
Yes |
Proprietary |
@suaveplan/events |
workspace:^ |
Event bus for key ring and partition lifecycle |
Low (monorepo) |
Yes |
Proprietary |
zod |
catalog:forms |
Runtime validation of all public option types |
Medium (npm, widely audited) |
Yes |
MIT |
@opentelemetry/api |
catalog:observability |
OTel span and metric APIs only |
Low (CNCF, stable spec) |
Yes |
Apache-2.0 |
tslib |
catalog:build |
TypeScript runtime helpers |
Low (Microsoft) |
Yes |
0BSD |
Supply-chain risk assessment
- Workspace packages (
@suaveplan/*) are built from the same monorepo lockfile (bun.lock) and published to a private Verdaccio instance. Compromise requires monorepo CI access.
- Zod is a mature, widely audited library with no native dependencies. Pinned via
catalog:forms and verified against bun.lock.
- @opentelemetry/api is a stable API surface (v1.x) maintained by the CNCF. No telemetry data leaves the process unless the host application wires an exporter.
- tslib is a Microsoft-maintained zero-dependency runtime helper. License (0BSD) is maximally permissive.
Tree-shakeability impact
- All
@suaveplan/* workspace packages are authored as ES modules with explicit exports and no side-effectful top-level code.
zod tree-shakes well; only used schemas are retained.
@opentelemetry/api is API-only; the SDK and exporters are not bundled.
- Expected dead-code elimination: if a consumer uses only grant/token management without cross-partition transfer, the resulting bundle should exclude
TransferManager and envelopeEncrypt implementations.
License compatibility
- All runtime dependencies are permissively licensed (MIT, Apache-2.0, 0BSD, or proprietary internal).
- No GPL, LGPL, or AGPL dependencies at runtime.
- Proprietary
@suaveplan/* packages are governed by the Suaveplan commercial license.
Operational readiness
Graceful degradation
- Read-only mode: If
PartitionStore reports unhealthy, PartitionManager transitions to read-only. create, addMember, removeMember, and update return SHARE_POLICY_VIOLATION with retryable: true and degraded: true. get, list, grantManager.check, and tokenManager.validate continue to operate.
- Encryption bypass disabled: If the crypto provider is unavailable, encrypted partitions refuse all operations rather than fall back to plaintext. Public partitions (encryption disabled) remain usable.
Resource limits
| Resource |
Default limit |
Configurable via |
| Max concurrent transfers |
64 |
TransferConfig.maxConcurrent |
| Max snapshot retention (per partition) |
10 000 |
PartitionManager constructor option |
| Max tokens per partition |
10 000 |
TokenManager internal cap (LRU eviction) |
| Max grants per partition |
10 000 |
GrantManager internal cap |
| Max keys per key ring |
100 000 |
KeyRing internal cap |
| Max policy check cache size |
1 000 |
PartitionManager LRU |
Error recovery
- Transient partition store unavailability: Exponential backoff with jitter (initial 50 ms, max 2 s, 3 retries). After retries, transition to read-only mode.
- Transfer failure mid-operation:
TransferManager implements two-phase transfer. If the import phase fails after a successful export, the exported file key is discarded and the transfer record is marked success: false.
- Crypto provider timeout: Operations time out after 5 s. Repeated timeouts (3 in 60 s) trigger read-only mode for encryption-dependent partitions.
Circuit breaker for storage backend
- Failure threshold: 5 errors in 60 seconds.
- Recovery timeout: 30 seconds.
- Half-open probe: 1
PartitionStore.get request every 10 seconds during recovery.
- Metric emitted:
share.storage_circuit_state (gauge: 0=closed, 1=open, 2=half-open).
Backup/restore compatibility
- Backup:
KeyRing.export produces a portable JSON array of UserWrappedKey objects. The format is versioned (keyring_format_version: 1) and documented.
- Restore:
KeyRing.import validates the format version and algorithm tags before ingesting. Unknown format versions throw SHARE_KEY_NOT_FOUND with unsupported_format: true.
- Partition backup:
PartitionStore.list + individual get calls can be serialised to a snapshot archive compatible with @suaveplan/drive SnapshotManager.
- Cross-preset compatibility: Key rings exported from the
encrypted preset can be imported into the shared preset provided the same master key is supplied.
Out of scope
The following capabilities are explicitly out of scope for this change:
- User management — identity providers, authentication flows, and user directories are handled by
@suaveplan/auth.
- Billing integration — no metered usage, payment gateways, or quota enforcement.
- Real-time collaboration (shared cursors) — no WebSocket presence, operational transforms, or live editing.
- Audit log storage — event emission is wired, but persistent audit log retention is delegated to downstream consumers.
- Public link indexing — no search engine optimisation, crawlers, or public directory listings.
Verification approach
Coverage target
- 100/100/100/100 coverage (statements/branches/functions/lines) required before merge.
- Istanbul coverage reports generated by
@vitest/coverage-istanbul and gated in CI.
Property-based test invariants (fast-check)
| Invariant |
Generator |
Assertion |
| Grant expiry |
fc.integer({ min: 1, max: 86400 }) TTL, fc.integer() clock offsets |
check(grantId) returns allowed: false when clock.now() > createdAt + TTL |
| Token revocation finality |
fc.string() token IDs |
After revoke(id), validate(id).valid is always false |
| Policy merge commutativity |
fc.record({ encryption: fc.boolean(), maxMembers: fc.integer() }) |
mergePolicies(a, b) for non-overlapping fields equals { ...a, ...b } |
| Partition member invariant |
fc.string() user IDs |
addMember(u) then removeMember(u) restores original member count |
| Key ring wrap/unwrap round-trip |
fc.uint8Array({ minLength: 16, maxLength: 32 }) keys |
unwrap(wrap(masterKey, dataKey)) is byte-identical to dataKey |
| Envelope encrypt/decrypt invertibility |
fc.uint8Array() data, fc.uint8Array(32) key |
envelopeDecrypt(key, envelopeEncrypt(key, data)) is byte-identical to data |
| Transfer rewrap correctness |
fc.uint8Array(32) keys |
rewrapKey(oldKEK, newKEK, wrapKey(oldKEK, DEK)) unwraps to original DEK under newKEK |
Load/stress test criteria
| Test |
Scenario |
Pass criteria |
grant_check_100k |
100 000 grantManager.check calls |
Duration < 500 ms, no memory growth |
token_validate_100k |
100 000 tokenManager.validate calls |
Duration < 500 ms, no memory growth |
key_ring_10k_keys |
addKey × 10 000 then getKey × 10 000 |
Duration < 2 s, memory < 20 MiB |
envelope_encrypt_100mb |
Encrypt 100 MiB in 1 MiB chunks |
Throughput ≥ 100 MiB/sec |
transfer_10gb |
Cross-partition transfer of 10 GiB |
Throughput ≥ 50 MiB/sec, no key leaks |
partition_create_10k |
Create 10 000 partitions |
Duration < 5 s, memory < 32 MiB |
Security audit checklist
Current-state audit (genesis)
The package does not exist on genesis yet — this is a fresh build. No prior source, no test results, no coverage data.
Available workspace deps on genesis
| Package |
Role |
@suaveplan/drive (workspace:^) |
Drive — the underlying virtual filesystem |
@suaveplan/error (workspace:^) |
Base class for DriveShareError; defineCodes for DRIVE_SHARE.* codes |
@suaveplan/types (workspace:^) |
Clock, Rng, LoggerLike, EventBusLike |
@suaveplan/crypto (workspace:^) |
AEAD, sign, agree — used in envelope encryption and key ring |
@suaveplan/crypto-keys (workspace:^) |
KeyPair, Keychain — used in key ring |
@suaveplan/events (workspace:^) |
EventBus for key ring and partition lifecycle events |
zod (catalog:forms) |
Zod schemas for all public option types |
@opentelemetry/api (catalog:observability) |
Spans + counters on all externally-visible operations |
tslib (catalog:build) |
Runtime helpers |
Dev deps: vitest, @vitest/coverage-istanbul, fast-check, mitata (all catalog:testing), @suaveplan/testing workspace:^.
Note: the main branch imports WebCryptoProvider from within the package using globalThis.crypto.subtle. Genesis keeps this approach — the package exports WebCryptoProvider and callers may substitute an alternative CryptoProvider implementation.
Preserved public API surface (from main branch)
Envelope encryption
Key ring
Partitions
Partition store
Partition policy
Sharing grants
Share tokens
Transfer
Common types
Error codes
New additions for genesis
1. Structured DriveShareError
DriveShareError extends SuaveplanError from @suaveplan/error carrying a DriveShareErrorCode discriminant. All throw sites use named factory helpers.
2. Zod schemas
PartitionManagerConfigSchema
CreatePartitionOptionsSchema
AddMemberOptionsSchema
CreateGrantOptionsSchema
CreateTokenOptionsSchema
TokenManagerConfigSchema
TransferOptionsSchema
PartitionPolicyConfigSchema
KeyRingConfigSchema
3. Injectable clock and RNG
TokenManager and PartitionManager accept clock?: Clock. All calls to Date.now() are replaced by clock.now(). generateId accepts an optional rng?: () => string (defaults to crypto.randomUUID).
4. OTel instrumentation
| Operation |
Signal |
partitionManager.create / delete |
span share.partition.create / delete |
partitionManager.addMember |
counter share.member.add_total |
grantManager.create / check |
span share.grant.create, counter share.grant.check_total |
tokenManager.create / validate |
span share.token.create, counter share.token.validate_total |
transferManager.transfer |
span share.transfer, histogram share.transfer_duration_ms |
keyRing.addKey / rotateKey |
counter share.key.add_total, span share.key.rotate |
5. AbortSignal on transfer
TransferOptions gains an optional signal?: AbortSignal. Long-running re-encryption operations abort on signal and throw DriveShareError(SHARE_TRANSFER_FAILED).
6. Property-based tests (fast-check)
- Grant expiry: for grants with TTL T, after advancing clock by T+1,
grantManager.check returns allowed: false.
- Token revocation finality: once
tokenManager.revoke(id) is called, validate(id).valid is always false regardless of subsequent calls.
- Policy merge commutativity for non-conflicting fields:
mergePolicies(a, b) for non-overlapping policy fields is equivalent to object spread.
- Partition member invariant:
addMember then removeMember leaves the partition with the same member count as before both calls.
7. Benchmark suite
grant_check_10k: 10 000 grantManager.check calls (in-memory, no IO).
token_validate_10k: 10 000 tokenManager.validate calls.
key_ring_100_keys: keyRing.addKey × 100 then getKey × 100.
envelope_encrypt_decrypt_10k_bytes: encrypt + decrypt a 10 KiB buffer.
File layout
Impact
Downstream packages: @suaveplan/drive-react-sharing (not yet on genesis) will depend on this. No existing genesis package depends on it.
Breaking changes from main-branch API: none. All main-branch call sites compile unchanged. New optional fields (clock, rng, signal) and error codes are additive.
Workspace dep prerequisites: @suaveplan/drive, @suaveplan/error, @suaveplan/types, @suaveplan/crypto, @suaveplan/crypto-keys, @suaveplan/events must be published to Verdaccio before this package can be built or tested.
Source mapping
REQUIRED for any package migrated from ../suaveplan/.
This change derives from ../suaveplan/enterprise/drive-sharing.md.
| Requirement |
Source lines |
Notes |
| Structured DriveShareError hierarchy |
L42, L61 |
verbatim — structured errors extending @suaveplan/error |
| Zod schemas for all public option types |
L38, L60 |
verbatim — Zod schemas for all public types; public API stability |
| Injectable clock and RNG |
L40 |
verbatim — deterministic behaviour; no Math.random() / Date.now() at module scope |
| OpenTelemetry instrumentation on all externally-visible operations |
L41, L70 |
verbatim — OTel for all public entrypoints; observability surface |
| AbortSignal on cross-partition transfer |
L43 |
reworded — backpressure & cancellation; AbortSignal everywhere async, applied specifically to TransferManager.transfer |
| CryptoProvider interface and WebCryptoProvider |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Envelope encryption and decryption |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Key wrap, unwrap, and rewrap |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Key ring management |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Partition policy creation and validation |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Partition store interface |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Partition manager CRUD and membership |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Grant manager create, check, and revoke |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Token manager create, validate, and revoke with TTL |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Cross-partition file transfer |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Branded ID utilities |
— |
derived from main-branch API surface preserved in proposal.md; no explicit line in enterprise spec |
| Property-based test invariants |
L39 |
verbatim — property-based tests (fast-check) for pure functions and state machines |
| Benchmark suite coverage |
L72 |
reworded — benchmark suite in src/__benchmarks__ with published numbers |
Requirements with no source line
| Requirement |
Justification |
| CryptoProvider interface and WebCryptoProvider |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface); enterprise spec does not enumerate methods individually |
| Envelope encryption and decryption |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Key wrap, unwrap, and rewrap |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Key ring management |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Partition policy creation and validation |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Partition store interface |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Partition manager CRUD and membership |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Grant manager create, check, and revoke |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Token manager create, validate, and revoke with TTL |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Cross-partition file transfer |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Branded ID utilities |
Preserved public API surface from main branch (see proposal.md § Preserved public API surface) |
| Benchmark suite coverage |
Genesis adds mitata benchmark suite and CI regression gate beyond main branch baseline |