@happyvertical/smrt-ingestion 0.57.3 → 0.57.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -207,3 +207,45 @@ Proposal limits must be positive safe integers. `maxHandlers`, `maxCandidates`
207
207
  and `maxSuggestions` are each capped at 20; `timeoutMs` is capped at 2147483647.
208
208
  Invalid limits are rejected when constructing `IngestionService`, before receipt
209
209
  or interpretation. See [REVIEW.md](REVIEW.md) for the published server review host.
210
+
211
+ ## Dispatch route ownership and legacy recovery
212
+
213
+ A receipt retains a versioned, server-owned `jobTarget` snapshot, and every
214
+ analysis dispatch retains the same route. Receipt replay and later analysis
215
+ cannot retarget it. `repairDispatches()` filters by retained route before the
216
+ calling host's authorization or delivery budget, then rechecks provenance under
217
+ the item lock. A failed job for another host sharing the same tenant and
218
+ confidential scope neither runs on this host nor blocks its unrelated receipt.
219
+ Matching routes still require current access within the captured permission
220
+ ceiling; their authorization and queue failures remain visible. Job arguments
221
+ continue to contain identifiers only.
222
+
223
+ Legacy receipts lacking route metadata can use existing recorded job authority
224
+ only when all available provenance agrees. A linked job must match the tenant,
225
+ ingestion queue, item, dispatch ID and revision exactly. This preserves recorded
226
+ job authority, not a reconstruction of the host's historical intention. Conflicting
227
+ or malformed provenance fails closed. Deleted jobs are absent provenance: an
228
+ existing protected route survives deletion, but without one the route remains
229
+ unknown and automatic repair skips it.
230
+
231
+ `inspectDispatchRoute(itemId)` requires normal read authority and returns a
232
+ status, fingerprint and verified target (or null). For genuinely provenance-free
233
+ legacy receipts a host may opt into `dispatchRecovery.authorize`. Without this
234
+ separate operator authorization callback recovery is disabled. Quiesce legacy
235
+ workers and investigate their recorded job history before authorizing recovery;
236
+ missing history is not proof of a particular intended handler. Call
237
+ `recoverDispatchRoute({ itemId, expectedFingerprint, evidenceRef })` with the
238
+ inspection fingerprint and a nonblank evidence reference of at most 512
239
+ characters. The target comes exclusively from that service's trusted,
240
+ constructor-snapshotted configuration, never from the request.
241
+
242
+ Recovery acquires the item lock, rechecks current/captured process permissions
243
+ and the separate host operator permission, and verifies the exact fingerprint.
244
+ It refuses bound, conflicting or stale authority. It appends retained operator,
245
+ date, evidence and original fingerprint provenance and binds missing dispatch
246
+ metadata atomically; it does not enqueue, alter original receipt/analysis/action
247
+ facts, or replace prior provenance. The exact original fingerprint/evidence retry
248
+ returns the retained binding, including under concurrent delivery, but still
249
+ rechecks both permissions. A different decision conflicts. Once reviewed,
250
+ normal matching-host `repairDispatches()` may enqueue work separately. Hosts
251
+ without legacy tenants need not configure recovery at all.
package/REVIEW.md CHANGED
@@ -166,3 +166,19 @@ wrapper `{ proposals: GenerationOutput }` under `analysis.result.output`.
166
166
  The factory unwraps this into `ItemReviewView.generation`. Stale generation is
167
167
  omitted while authorized saved reviews remain available; access denials propagate.
168
168
  The reference application still owns its fixture provisioning and HTTP transport.
169
+
170
+ ## Explicit upload retries
171
+
172
+ The inbox retains selected original files and the receive request identity when
173
+ upload fails or acknowledgment is lost. Retry Upload explicitly with the same
174
+ selection; Refresh does not replace that identity. Selecting files again starts a
175
+ new receipt identity, even when names match. Successful upload clears the selection
176
+ and identity. Replacing the authenticated host/context or destroying the component
177
+ discards both and fences late completion from the prior context. No automatic
178
+ upload retry or authorization bypass occurs.
179
+
180
+ The inbox clears only its native file-input value when opening the picker, so
181
+ choosing the same local file explicitly starts a new upload identity. Opening
182
+ then dismissing the chooser preserves the separately retained originals and
183
+ request identity for retry; it does not clear the shared FilePicker's native-form
184
+ behavior. Successful upload and host/context disposal still discard retry state.
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-ingestion",
5
- "packageVersion": "0.57.3",
5
+ "packageVersion": "0.57.5",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-ingestion:IntakeItem": {
8
8
  "name": "intakeitem",