feat(drive): expose authorized typed Workspace Drive API
T-722: reuse T-721 storage/CAS/receipts with clone-bound transaction authorization against attached Server authority. Add migration 84 audited Worker read_only/read_write grants and removal/deletion fencing, member-facing ordinary access, owner-controlled grant settings, Workspace-bound decimal entry references, bounded text/binary chunks, streamed HTTP receive/download with integrity and safe headers, typed errors and generated Rust/OpenAPI/TypeScript contracts. Validation: root cargo check; server-api 83 default / 91 typescript tests; FeatureStorage 16; Drive 31 unit + 12 integration; Workspace Server 691 library + 11 binary tests (--test-threads=4), including 9 real DB/LocalFileSystem HTTP tests for two Workers/non-owner usage, revoke during reception, concurrent CAS, response-loss receipts, chunk expiry and safe binary media. cargo fmt --all -- --check and git diff --check HEAD passed. Existing OpenAPI schemas/routes semantically unchanged; dependent TS digest projections regenerated.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-companion-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:16796bde0da04973310a14f90cf6eac14b2580bbe184c7c12afde3b6225ce933)
|
||||
// Input contract: 0.1.0 (sha256:5f767ab90e6507d2e9486cd2efe74f62d613912ffa830ad617a088b2848f20da)
|
||||
// Options: companion-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/companion-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_companion_api_types -- --check
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
// Generated from server-api. Do not edit by hand.
|
||||
// Regenerate: cargo run -q -p server-api --features typescript --example generate_drive_api_types > web/workspace/src/lib/generated/drive-api.ts
|
||||
|
||||
export type DriveEntryRef = { workspace_id: string; node_id: string };
|
||||
|
||||
export type DriveEntryKind = "folder" | "file";
|
||||
|
||||
export type DriveEntry = {
|
||||
entry: DriveEntryRef;
|
||||
parent: DriveEntryRef | null;
|
||||
name: string;
|
||||
kind: DriveEntryKind;
|
||||
revision: string;
|
||||
/**
|
||||
* File length in bytes; absent for folders.
|
||||
*/
|
||||
size: number | null;
|
||||
content_type: string | null;
|
||||
updated_by: string;
|
||||
/**
|
||||
* Timestamp projected from storage's updated_at_ms; not a creation time.
|
||||
*/
|
||||
updated_at: string;
|
||||
/**
|
||||
* Stable relative authenticated URL in this same Workspace. No bearer token
|
||||
* or cross-Workspace link is embedded in this metadata.
|
||||
*/
|
||||
latest_url: string;
|
||||
};
|
||||
|
||||
export type DriveEntryQuery = { entry_workspace_id: string; id: string };
|
||||
|
||||
export type DriveListQuery = {
|
||||
entry_workspace_id: string;
|
||||
/**
|
||||
* Folder to list.
|
||||
*/
|
||||
id: string;
|
||||
limit: number | null;
|
||||
/**
|
||||
* Opaque service-issued page cursor, not a bare node ID.
|
||||
*/
|
||||
after: string | null;
|
||||
};
|
||||
|
||||
export type DriveSearchQuery = {
|
||||
query: string;
|
||||
/**
|
||||
* Search file text as well as names only when explicitly requested.
|
||||
*/
|
||||
include_text: boolean;
|
||||
limit: number | null;
|
||||
after: string | null;
|
||||
};
|
||||
|
||||
export type DriveListResponse = {
|
||||
entries: Array<DriveEntry>;
|
||||
next_after: string | null;
|
||||
};
|
||||
|
||||
export type DriveReadTextQuery = {
|
||||
entry_workspace_id: string;
|
||||
id: string;
|
||||
max_bytes: number;
|
||||
};
|
||||
|
||||
export type DriveReadTextResponse = {
|
||||
entry: DriveEntry;
|
||||
text: string;
|
||||
truncated: boolean;
|
||||
};
|
||||
|
||||
export type DriveReadChunkQuery = {
|
||||
entry_workspace_id: string;
|
||||
id: string;
|
||||
/**
|
||||
* Bind a multi-chunk read to the same file revision.
|
||||
*/
|
||||
expected_revision: string;
|
||||
offset: number;
|
||||
length: number;
|
||||
};
|
||||
|
||||
export type DriveDownloadQuery = {
|
||||
entry_workspace_id: string;
|
||||
id: string;
|
||||
expected_revision: string | null;
|
||||
};
|
||||
|
||||
export type DriveMutation = {
|
||||
"operation": "create_folder";
|
||||
parent: DriveEntryRef;
|
||||
name: string;
|
||||
} | {
|
||||
"operation": "create_text";
|
||||
parent: DriveEntryRef;
|
||||
name: string;
|
||||
text: string;
|
||||
content_type: string;
|
||||
} | {
|
||||
"operation": "update_text";
|
||||
id: DriveEntryRef;
|
||||
expected_revision: string;
|
||||
text: string;
|
||||
content_type: string;
|
||||
} | {
|
||||
"operation": "relocate";
|
||||
id: DriveEntryRef;
|
||||
expected_revision: string;
|
||||
parent: DriveEntryRef;
|
||||
name: string;
|
||||
} | { "operation": "delete"; id: DriveEntryRef; expected_revision: string };
|
||||
|
||||
export type DriveMutationRequest = {
|
||||
request_id: string;
|
||||
mutation: DriveMutation;
|
||||
};
|
||||
|
||||
export type DriveMutationResponse = {
|
||||
request_id: string;
|
||||
/**
|
||||
* A deleted entry has no live metadata.
|
||||
*/
|
||||
entry: DriveEntry | null;
|
||||
};
|
||||
|
||||
export type DriveUploadOperation = "create" | "update";
|
||||
|
||||
export type DriveUploadQuery = {
|
||||
operation: DriveUploadOperation;
|
||||
request_id: string;
|
||||
entry_workspace_id: string;
|
||||
parent_id: string | null;
|
||||
name: string | null;
|
||||
id: string | null;
|
||||
expected_revision: string | null;
|
||||
content_type: string;
|
||||
/**
|
||||
* Values above the file limit still decode as u32 so the service returns
|
||||
* typed Limit rather than a generic request-decoding error.
|
||||
*/
|
||||
size: number;
|
||||
sha256: string;
|
||||
};
|
||||
|
||||
export type DriveRequestState = "uncommitted" | "committed";
|
||||
|
||||
export type DriveRequestStatusResponse = {
|
||||
request_id: string;
|
||||
state: DriveRequestState;
|
||||
response: DriveMutationResponse | null;
|
||||
};
|
||||
|
||||
export type DriveAccess = "read_only" | "read_write";
|
||||
|
||||
export type DriveGrantCreateRequest = {
|
||||
runtime_id: string;
|
||||
worker_id: string;
|
||||
access: DriveAccess;
|
||||
};
|
||||
|
||||
export type DriveGrantResponse = {
|
||||
grant_id: string;
|
||||
workspace_id: string;
|
||||
runtime_id: string;
|
||||
worker_id: string;
|
||||
access: DriveAccess;
|
||||
revoked: boolean;
|
||||
created_by: string;
|
||||
created_at: string;
|
||||
revoked_by: string | null;
|
||||
revoked_at: string | null;
|
||||
};
|
||||
|
||||
export type DriveGrantListQuery = {
|
||||
limit: number | null;
|
||||
/**
|
||||
* Canonical grant ID cursor within this Workspace.
|
||||
*/
|
||||
after: string | null;
|
||||
};
|
||||
|
||||
export type DriveGrantListResponse = {
|
||||
grants: Array<DriveGrantResponse>;
|
||||
next_after: string | null;
|
||||
};
|
||||
|
||||
export type DriveApiErrorCode =
|
||||
| "denied"
|
||||
| "not_found"
|
||||
| "conflict"
|
||||
| "invalid"
|
||||
| "limit"
|
||||
| "storage_unavailable"
|
||||
| "outcome_unknown";
|
||||
|
||||
export type DriveFailureClassification = "not_committed" | "unknown";
|
||||
|
||||
export type DriveApiError = {
|
||||
code: DriveApiErrorCode;
|
||||
classification: DriveFailureClassification;
|
||||
message: string;
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-repository-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:16796bde0da04973310a14f90cf6eac14b2580bbe184c7c12afde3b6225ce933)
|
||||
// Input contract: 0.1.0 (sha256:5f767ab90e6507d2e9486cd2efe74f62d613912ffa830ad617a088b2848f20da)
|
||||
// Options: repository-operation-schema-closure,openapi-3.1,format:uint64=safe-number,strict-safe-integers,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/repository-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_repository_openapi_types -- --check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-runtime-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:16796bde0da04973310a14f90cf6eac14b2580bbe184c7c12afde3b6225ce933)
|
||||
// Input contract: 0.1.0 (sha256:5f767ab90e6507d2e9486cd2efe74f62d613912ffa830ad617a088b2848f20da)
|
||||
// Options: runtime-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/runtime-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_runtime_api_types -- --check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-ticket-browser-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:16796bde0da04973310a14f90cf6eac14b2580bbe184c7c12afde3b6225ce933)
|
||||
// Input contract: 0.1.0 (sha256:5f767ab90e6507d2e9486cd2efe74f62d613912ffa830ad617a088b2848f20da)
|
||||
// Options: ticket-objective-merge-request-browser-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/ticket-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_ticket_api_types -- --check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-worker-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:16796bde0da04973310a14f90cf6eac14b2580bbe184c7c12afde3b6225ce933)
|
||||
// Input contract: 0.1.0 (sha256:5f767ab90e6507d2e9486cd2efe74f62d613912ffa830ad617a088b2848f20da)
|
||||
// Options: worker-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/worker-launch-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_worker_launch_api_types -- --check
|
||||
|
||||
Reference in New Issue
Block a user