Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/app/lib/backup_streaming.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Backup Streaming Service

Implements ADR-015 Phase 2: Streaming backup download with chunked transfer encoding.
Implements ADR-015 Phase 1: Streaming backup download with chunked transfer encoding.
Converts backup dictionaries into JSON or GEXF streams without loading entire backup into memory.

Supports two formats:
Expand Down
3 changes: 0 additions & 3 deletions cli/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ import {
DissolveResponse,
SystemStatusResponse,
BackupRequest,
BackupResponse,
ListBackupsResponse,
RestoreRequest,
RestoreResponse,
ResourceCreate,
ResourceRead,
ResourceUpdate,
Expand Down
39 changes: 6 additions & 33 deletions cli/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,22 +685,9 @@ export interface BackupRequest {
format?: 'archive' | 'json' | 'gexf'; // Export format: archive (tar.gz with documents, default), json (graph only), or gexf (Gephi visualization)
}

export interface BackupIntegrityAssessment {
external_dependencies_count: number;
warnings_count: number;
issues_count: number;
has_external_deps: boolean;
details: Record<string, any>;
}

export interface BackupResponse {
success: boolean;
backup_file: string;
file_size_mb: number;
statistics: Record<string, number>;
integrity_assessment?: BackupIntegrityAssessment;
message: string;
}
// BackupIntegrityAssessment / BackupResponse removed in ADR-102 P6: the backup route
// streams the file (createBackup returns {filename,path,size}); the Python-side
// BackupResponse/BackupIntegrityAssessment models were deleted in P6a.

export interface BackupInfo {
filename: string;
Expand All @@ -715,23 +702,9 @@ export interface ListBackupsResponse {
count: number;
}

export interface RestoreRequest {
username: string;
password: string;
backup_file: string;
// ADR-102 P4: restore merge mode (replaces overwrite + handle_external_deps).
mode?: 'idempotent' | 'adjacent' | 'integration';
// ADR-102 P5: epoch reconciliation. 'faithful' is clone-only (idempotent + empty target).
epoch?: 'simple' | 'faithful';
}

export interface RestoreResponse {
success: boolean;
restored_counts: Record<string, number>;
warnings: string[];
message: string;
// external_deps_handled removed in ADR-102 P6 (dead field; restore uses --mode/--epoch)
}
// RestoreRequest / RestoreResponse removed in ADR-102 P6: restoreBackup() uses
// positional args (backupFilePath, mode, onUploadProgress, epoch) + multipart
// FormData and returns an inline result type — these interfaces were never used.

// ========== RBAC Types (ADR-028) ==========

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,21 @@ deciders:
related:
- ADR-012
- ADR-013
- ADR-102
---

# ADR-015: Backup/Restore Streaming Architecture

> **Status update (ADR-102, 2026):** the client-controlled streaming model decided
> here is live. **Phase 1 (backup download)** ships as
> `api/app/lib/backup_streaming.py` + `backup_archive.py`. **Phase 2 (restore upload)**,
> tracked below as "🚧 IN PROGRESS", was *delivered* by
> [ADR-102](ADR-102-portable-backup-and-restore-with-clone-merge-semantics.md) — the
> portable `kg-backup/2` format with clone/merge/restamp restore semantics, epoch
> reconciliation, and the async `restore_worker`. ADR-102 builds **on** this ADR's
> streaming foundation rather than replacing it, so ADR-015 remains Accepted; the
> Phase-2 progress markers below are historical (read them as "done, see ADR-102").

## Overview

Think about how you back up photos from your phone. The photos live on your device, not on some cloud server. You initiate the backup, your phone sends the files where you want them, and you can restore them whenever needed. Now imagine if instead, all your photos were "backed up" to a folder on Apple's servers that you couldn't even access - that would be pretty useless, right?
Expand Down
Loading