# Story 4D Spec: Close Public-Folder Runtime Parity

Validated on 2026-04-01 against the current `megalib` tree, the Rust graph `project`, the upstream C++ graph `sdk`, and the sibling upstream SDK at `../sdk`.

This document refines Story 4D from `agents/outputs/architectural_parity_epic.md` into an implementation-ready planning story. Its job is to close the separate public-folder runtime gap that remains after Story 1, Story 3, and Story 4B: Rust already has `src/public.rs` as a distinct runtime, but it still lacks the cache/session-continuity behavior that makes upstream folder-link handling a first-class runtime path rather than a cold-fetch helper.

Companion artifacts:

- `agents/outputs/architectural_parity_epic.md`
- `agents/outputs/architectural_parity_story_1_core_engine_boundary.md`
- `agents/outputs/architectural_parity_story_3_persistence_spi.md`
- `agents/outputs/architectural_parity_story_4b_production_persistence_backend.md`
- `agents/outputs/architectural_parity_story_12_validation_harness.md`

---

## Status

Not started.

Current implementation status on 2026-04-01:

- `src/public.rs` already provides a separate public-folder runtime entrypoint through `open_folder(...)`
- `PublicFolder` already exposes browse and download helpers over a parsed cached node set
- `Session` already exposes `FolderSessionBlob` parse/dump helpers for SDK-compatible folder-link session blobs
- the public-folder runtime still behaves like a cold fetch path:
  - no runtime-owned durable cache scope
  - no persisted public-folder tree restore path
  - no repeated-open/session-resume continuity comparable to upstream folder-link caching
- Story 3 and Story 4B intentionally left public-link persistence disabled or out of scope

This means the structural split exists, but the runtime-parity story does not.

---

## Story Goal

Preserve `src/public.rs` as a distinct runtime while adding the missing public-folder continuity layer:

- folder-link session identity has a named runtime owner
- cached public-folder tree state can survive reopen or session-resume flows
- folder-link auth/session shaping remains separate from authenticated-session architecture
- public-folder runtime parity becomes an owned implementation story rather than a residual note in Story 1

---

## Why This Story Exists

The upstream SDK treats folder-link access as a real second runtime path inside `MegaClient`, not as a one-shot unauthenticated helper. The relevant ground truth is:

- folder-link state and auth/session shaping in `../sdk/include/mega/megaclient.h`
- folder-link-specific runtime handling in `../sdk/src/megaclient.cpp`
- outward folder-link request/result handling in `../sdk/src/megaapi_impl.cpp`

Current Rust already respects one important architectural fact:

- public-folder work is not forced into the authenticated actor

But the remaining gap is equally important:

- the separate runtime still lacks durable continuity

Without Story 4D, the epic can finish the authenticated persistence stories and still leave folder-link parity materially behind the upstream SDK.

---

## Scope

In scope:

- define the internal runtime owner for public-folder continuity
- define the durable scope identity for folder-link persistence
- persist and restore public-folder session metadata and cached folder tree state
- route repeated `open_folder(...)` and folder-session-resume flows through that runtime
- add validation coverage for repeated open, session-blob round-trip, stale-cache fallback, and invalidated-link behavior

Out of scope:

- forcing public-folder flows into authenticated `Session`
- public-folder event APIs
- sync, backup, mount, or side-service work
- generic transfer-runtime redesign
- widening the public API unless one small additive helper is clearly required

This story is successful if the separate runtime remains separate and also gains a real continuity model.

---

## Story 1, Story 3, And Story 4B Constraints

Story 4D must preserve these existing decisions:

- public-folder runtime remains separate from the authenticated actor
- Story 3 remains the generic persistence-SPI story, not the place where public-folder continuity was solved
- Story 4B remains the authenticated production-backend rollout story, not the place where folder-link continuity was solved
- no-op or disabled persistence in earlier stories was an intentional temporary narrowing, not the final parity answer
- public API changes, if any, must be additive

If implementation pressure suggests collapsing folder-link state into authenticated `Session`, the design is wrong and the story should be narrowed rather than widened.

---

## SDK Parity Target

Story 4D should align with the upstream SDK in these ways:

1. Folder-link access remains a distinct runtime path from full-account sessions.
2. Folder-link session metadata and cached node state have explicit runtime ownership.
3. Restart/reopen continuity for folder-link browsing does not rely on a full cold fetch every time.
4. Cache invalidation falls back cleanly to the server path instead of poisoning the runtime.

Rust should stay idiomatic:

- do not clone `MegaClient` internals one-for-one
- do keep the runtime separate from authenticated `Session`
- do use one clear folder-link persistence scope rather than hiding folder data in account-scoped state

---

## Design Decisions

### Decision 1. Public-folder runtime stays separate

Why:

- Story 1 already fixed that boundary
- the current `src/public.rs` split is architecturally correct

Consequence:

- Story 4D may reuse lower persistence helpers
- Story 4D must not reroute public-folder work through the authenticated actor

### Decision 2. Folder-link persistence scope must be distinct from authenticated account scope

Why:

- Story 3 and Story 4B currently model persistence scope around authenticated account identity
- upstream cache scoping covers folder-link identity too
- folder-link continuity cannot be modeled honestly as “just another account handle”

Consequence:

- Story 4D may widen the internal persistence-scope model or add a sibling folder-link scope type
- folder-link durable identity should be derived from stable folder-link session metadata such as public handle or equivalent runtime identity, not from an authenticated account handle

### Decision 3. The durable substrate is folder-session metadata plus cached public-folder tree state

Why:

- current Rust already has `FolderSessionBlob` support
- current Rust already materializes a public-folder node tree in memory
- that pair is the natural first continuity substrate

Consequence:

- Story 4D should persist:
  - folder-link session metadata sufficient to restore runtime identity
  - cached public-folder tree state
- Story 4D should not persist unrelated authenticated-session fields

### Decision 4. Cache failure falls back to cold open

Why:

- folder-link continuity is cache-like, not authoritative account truth
- bad folder-link cache data should not block use of a still-valid link

Consequence:

- malformed, stale, or invalidated public-folder cached state should be treated as a recoverable cache miss
- repeated open should fall back to the server path when needed

### Decision 5. Public API should stay stable unless one narrow additive helper is needed

Why:

- `open_folder(...)` already exists and is the correct public entrypoint
- continuity work is primarily internal

Consequence:

- Story 4D should preserve `open_folder(...)`
- if a helper such as `open_folder_with_session_blob(...)` is added, it must be clearly additive and narrowly justified

---

## Recommended Rust Shape

One acceptable internal direction is:

```rust
// illustrative only

pub(crate) struct PublicFolderRuntime {
    persistence: PublicFolderPersistence,
}

pub(crate) struct PersistedPublicFolderState {
    pub(crate) session: FolderSessionBlob,
    pub(crate) tree: PersistedPublicFolderTree,
}
```

The exact types may differ. The architectural requirements are:

- one internal owner for folder-link continuity
- one distinct persistence scope for folder-link state
- one cached public-folder tree model
- clean fallback from restore failure to cold fetch

Story 4D may keep that ownership in `src/public.rs` or split helper modules if the write set stays small and the public runtime shape stays obvious.

---

## Affected Modules

Expected primary touch points:

- `src/public.rs`
- `src/session/core.rs`
- `src/session/runtime/persistence.rs`

Possible supporting modules:

- additive internal helpers adjacent to `src/public.rs`
- tests under `tests/` once Story 12 harness structure is available, or focused module tests before then

---

## Agent-Sized Tasks

### Task 4D.1

Define the public-folder continuity owner and durable model.

### Task 4D.2

Add persistence-scope resolution and restore/save helpers for folder-link state.

### Task 4D.3

Route repeated `open_folder(...)` and folder-session-resume flows through the continuity layer.

### Task 4D.4

Add focused regression coverage for repeated open, invalidated cache fallback, and folder-session round-trip behavior.

---

## Acceptance Criteria

Story 4D is complete when:

1. public-folder runtime continuity has an owning implementation story and code path, not only Story 1 prose
2. folder-link runtime remains separate from authenticated-session architecture
3. folder-link session metadata plus cached public-folder tree state have explicit durable ownership
4. repeated open or resume flows can restore cached folder state when valid
5. malformed or stale folder-link persisted state falls back cleanly to a cold open path
6. public-folder parity can be validated independently from authenticated-session persistence

---

## Verification Requirements

Because this is a future Rust-touching story, each implementation slice must end with:

```bash
cargo fmt --all
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all
```

Focused coverage should include:

- folder-session-blob round-trip
- repeated `open_folder(...)` behavior
- stale or malformed folder-link cache fallback
- invalidated folder-link restore failure followed by cold refetch

---

## Relationship To Later Stories

Story 4D closes the separate public-folder runtime gap.

Later work should consume it like this:

- Story 12 should add public-folder restart and repeated-open parity scenarios against this runtime
- later public-folder event or adapter work, if ever added, must build on the separate runtime rather than collapsing it into authenticated `Session`

The key architectural rule is:

- folder-link runtime remains separate
- Story 4D makes that separate runtime durable and restart-aware
