Qualify durable purchase and media primitives and preserve app launch paths
This commit is contained in:
@@ -151,3 +151,49 @@ subsequent combined isolated Rust run also passed its independent golden fixture
|
||||
test, establishing agreement across both implementations. Node caller/serving
|
||||
integration and live acceptance remain open. No fixture or Rust source changed
|
||||
between the frozen compilation inputs and the successful run.
|
||||
|
||||
## Immutable serving and rental caller work
|
||||
|
||||
The next local source connects explicit producer/project approval to the fixed
|
||||
`indeedhub-api` installation pin and stores a separate immutable serving mapping
|
||||
before returning the signed registration receipt. It does not insert filenames
|
||||
into the legacy mutable share catalog. Its canonical ordered-array terms hash has
|
||||
an independently generated Node.js fixture. Original Cloud source deletion does
|
||||
not change the saved snapshot, registration receipt or rental terms.
|
||||
|
||||
A peer GET to `/content/{registered_id}/rental/{purchase_uuid}` now requires the
|
||||
existing node proof signed for that exact path and the original
|
||||
`X-Content-Capability`. The node verifies its own durable seller `ReceiptSaved`
|
||||
record, authenticated buyer, immutable content/hash/size/terms and settlement
|
||||
amount. Invalid ranges reject before a rental starts. First successful durable
|
||||
stream authorization records one rental window; reopen and range requests keep
|
||||
that same deadline. Stream reads use bounded 64 KiB buffers, reject clock rollback
|
||||
and stop new reads at expiry. HEAD and preflight do not start a window.
|
||||
|
||||
This is a server access window, not DRM. Bytes already delivered cannot be
|
||||
revoked. A crash after the lease is fsynced but before the first network byte still
|
||||
consumes elapsed time: local persistence and remote byte delivery are not one
|
||||
atomic operation. The player must display the persisted expiry and reuse the
|
||||
original purchase/capability on reconnect, not create another payment.
|
||||
|
||||
Seven registered-media tests and three route/stream tests passed in
|
||||
`/tmp/archy-registration-rental-batch-tests.log`; its overall result was 1,834
|
||||
passed, one failed legacy missing-file expectation, and five existing skips.
|
||||
All 383 captured source/build/fixture hashes remained unchanged. The expectation
|
||||
was corrected separately and awaits the next full run. Do not describe that batch
|
||||
as a clean combined suite or live playback acceptance.
|
||||
|
||||
The subsequent, not-yet-tested performance refinement persists the already
|
||||
verified snapshot's signed hash and inode/device/ctime/size attestation during
|
||||
registration. Ordinary first-open/range requests reuse it. A missing cache streams
|
||||
the original signed hash under a per-registration lock; buyer leases use separate
|
||||
per-purchase locks. Large verification reads do not hold the global metadata lock
|
||||
or start a rental while queued. An identical concurrent cache writer is accepted
|
||||
only after exact readback and file/directory fsync. Three additional tests cover
|
||||
lock independence, cache reconstruction and mismatched-cache refusal.
|
||||
|
||||
Owner-session/CSRF approval RPC, producer-signed exact selection, native Cloud
|
||||
picker/consent bridge, app receipt consumption, and player reconnect/expiry UI are
|
||||
being connected next. Their source is not yet deployed; app registration and
|
||||
publication flags remain disabled pending complete qualification. No real payment,
|
||||
announcement, media publication or node deployment was performed by this work.
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# Installer-owned IndeeHub registration identity
|
||||
|
||||
Status: source compiled and eight installer/orchestrator tests passed in the
|
||||
combined isolated backend run. That run has one unrelated FIPS binding test
|
||||
failure (1,821 passed, one failed, five existing skips), so combined qualification
|
||||
is not clean. The separate container manifest test passed. No deployment
|
||||
or actual-node acceptance. This adds an installation prerequisite; it does not
|
||||
enable registration or publication.
|
||||
|
||||
The IndeedHub API manifest explicitly opts in with
|
||||
`container.media_registration_identity: true`. The field defaults to false and
|
||||
is omitted from serialized ordinary manifests. Only opted-in apps read the
|
||||
existing node identity or receive registration identity variables.
|
||||
|
||||
The production install/reconcile environment chokepoint loads the existing node
|
||||
key, verifies its derived public key matches `identity/node_key.pub`, and asks the
|
||||
private installation store for a stable pin. Missing or mismatching identity
|
||||
files fail; no node key is generated, repaired or replaced. The helper runs on a
|
||||
blocking worker and uses bounded cross-process locking plus durable no-replace
|
||||
writes.
|
||||
|
||||
The public identity values injected are:
|
||||
|
||||
- `ARCHIPELAGO_REGISTRATION_NODE_PUBLIC_KEY`: exact existing Ed25519 public key.
|
||||
- `ARCHIPELAGO_REGISTRATION_NODE_DID`: its matching did:key identity.
|
||||
- `ARCHIPELAGO_REGISTRATION_AUDIENCE`: one persisted UUID for this installed app.
|
||||
|
||||
These are public identity bindings, not secret signing keys. They are derived
|
||||
from authenticated installation state. Manifest plaintext duplicates are replaced
|
||||
by the authoritative pins; derived/secret-backed attempts to override these names
|
||||
are rejected. Existing native-signing user identities are unrelated to this node
|
||||
receipt-signing identity. `NODE_IDENTITY_PUBKEYS` is not used for this purpose.
|
||||
No `_ENABLED` setting is written. No unrelated app receives these values.
|
||||
|
||||
## Persistence and recovery
|
||||
|
||||
The node keeps private 0600 records beneath the 0700 directory
|
||||
`<node-data>/app-registration-pins/`:
|
||||
|
||||
- `<app-id>.json`: version, app ID, node public key/DID and stable app audience.
|
||||
- `<app-id>.initialized.json`: version, app ID and canonical pin-record SHA256.
|
||||
|
||||
Provisioning returns only after both files and their directory are fsynced.
|
||||
Interrupted initial provisioning after pin persistence finishes its marker on
|
||||
retry without changing the audience. A missing pin with a surviving marker is
|
||||
an error requiring recovery of the original pin, not permission to generate a
|
||||
replacement. Damaged, unreadable, symlinked or mismatched files remain untouched.
|
||||
A node identity change also requires an explicit migration; it does not silently
|
||||
repin an existing app.
|
||||
|
||||
`load_existing` is the future bridge/RPC lookup: it never creates files or app
|
||||
identity. It requires matching complete persisted records. The bridge must bind
|
||||
the actual installed frontend/backend relationship: IndeedHub's UI app is
|
||||
`indeedhub`, while its API and this stored registration scope are `indeedhub-api`.
|
||||
Arbitrary apps must not select another installed scope by sending its name.
|
||||
|
||||
The audience survives app upgrade, ordinary restart, repeated reconciliation,
|
||||
failed install retry and reinstall that preserves the app database. This change
|
||||
contains no pin deletion API or uninstall hook. It does not alter uninstall
|
||||
choices, persistent app data, original Cloud files, wallet data or outstanding
|
||||
media snapshots/rentals.
|
||||
|
||||
Explicit full data deletion is a separate operator decision. A future reset
|
||||
workflow must coordinate deletion of app database/intents and pin state, and must
|
||||
preserve or resolve outstanding node media/payment obligations before allowing a
|
||||
new audience. Removing only one pin file is not a supported reset. Merely
|
||||
uninstalling/reinstalling an app must not rotate its audience. If all installation
|
||||
records are externally destroyed, this store cannot distinguish that from a
|
||||
first installation; restore them along with the original app database rather than
|
||||
re-enabling registration against a new audience.
|
||||
|
||||
## Prepared local checks
|
||||
|
||||
The patch adds five isolated store/env tests, three production-orchestrator
|
||||
chokepoint tests and one manifest test. They cover stable retry/reload, distinct
|
||||
app audiences, concurrent provisioning, key preservation, corruption/missing-pin
|
||||
and foreign-key rejection, interrupted marker completion, symlink rejection,
|
||||
authoritative/idempotent environment rendering, no implicit enablement, unrelated
|
||||
apps without identity, and existing-key/public-key consistency. Fixtures use
|
||||
private temporary directories and mock runtime calls only.
|
||||
|
||||
The combined run used `scripts/test-backend-isolated.sh`; all five store/env and
|
||||
three orchestrator tests passed. Log:
|
||||
`/tmp/archy-indeehub-executor-combined-tests.log`. All 377 captured source/build
|
||||
input hashes remained unchanged through the run; provenance is recorded in
|
||||
`/tmp/archy-indeehub-executor-combined-provenance.json`. The single failure is
|
||||
`fips::dial::tests::purchase_post_serializes_once_and_binds_the_actual_bytes_to_the_peer`.
|
||||
Do not treat this as a clean combined suite. The container crate manifest test
|
||||
still needs its scoped isolated run in the next coordinated slot. There is no
|
||||
node deployment, catalog publication or app registration from this change.
|
||||
|
||||
Qualification update: the scoped isolated container run passed
|
||||
`manifest::tests::media_registration_identity_is_explicit_and_preserved` (one
|
||||
passed, zero failed, 82 filtered), with all 11 container/workspace input hashes
|
||||
unchanged. Log: `/tmp/archy-registration-container-manifest-test.log`. The later
|
||||
combined backend batch passed all installer tests again; its overall 1,834 passed,
|
||||
one failed legacy missing-file expectation and five existing skips is not a clean
|
||||
combined suite. Source remains undeployed.
|
||||
|
||||
## Combined qualification after resumed integration
|
||||
|
||||
The full isolated backend rerun passed 1,848 tests with zero failures and five
|
||||
existing skips. All 385 recorded source, build and fixture hashes remained
|
||||
unchanged. Evidence: `/tmp/archy-qualified-candidate-backend-rerun-tests.log` and
|
||||
`/tmp/archy-qualified-candidate-backend-rerun-provenance.json`. Earlier failed
|
||||
runs remain recorded. This qualifies the current backend primitives and Browse
|
||||
path repair locally; production build and live deployment checks are next.
|
||||
Complete purchase callers, app registration/publication and timed playback
|
||||
acceptance remain open. No real payment or public publication was performed.
|
||||
@@ -277,3 +277,22 @@ leave animation, and the song catalog loaded after bridge initialization. Hidden
|
||||
iframe checks now use interval polling because animation-frame polling stops
|
||||
when hidden. Timeouts were not increased. These browser passes do not establish
|
||||
physical companion acceptance or replace the remaining lifecycle checks.
|
||||
|
||||
Publication review must also inventory the Yaya demo's visual assets in local
|
||||
platform commits. A node-restricted promotion does not make a tracked asset or
|
||||
Git commit private after publication. This worktree is not authorization to push
|
||||
private demo source or derived private assets to either public mirror; retain
|
||||
private delivery and prepare a separately reviewed public-safe contribution if
|
||||
those assets are not approved for public distribution. No source publication was
|
||||
performed during the resumed deployment and qualification work.
|
||||
|
||||
## Combined qualification after resumed integration
|
||||
|
||||
The full isolated backend rerun passed 1,848 tests with zero failures and five
|
||||
existing skips. All 385 recorded source, build and fixture hashes remained
|
||||
unchanged. Evidence: `/tmp/archy-qualified-candidate-backend-rerun-tests.log` and
|
||||
`/tmp/archy-qualified-candidate-backend-rerun-provenance.json`. Earlier failed
|
||||
runs remain recorded. This qualifies the current backend primitives and Browse
|
||||
path repair locally; production build and live deployment checks are next.
|
||||
Complete purchase callers, app registration/publication and timed playback
|
||||
acceptance remain open. No real payment or public publication was performed.
|
||||
|
||||
@@ -581,3 +581,23 @@ unchanged backend/session/app containers and rollback at
|
||||
Evidence: `/tmp/archy-payment-switch-dev-deploy.log`. Framework is reachable and
|
||||
healthy but runs a different backend/UI revision; this incremental deployment
|
||||
has not changed it.
|
||||
|
||||
Read-only real-attempt validation: Yaya's existing `lnd.paymentstatus` RPC returns
|
||||
`failed`, `Insufficient channel balance`, and 2 sats for the operator's reported
|
||||
Lightning attempt. This verifies the deployed compatibility UI's recovery lookup
|
||||
against the actual existing backend, rather than only fixtures. Private evidence:
|
||||
`/tmp/archy-payment-switch-incident/yaya-failed-lightning-rpc-result.private.json`.
|
||||
The check did not pay, retry a payment, change a receipt, or infer seller invoice
|
||||
cancellation. Browser interaction with the operator's own saved attempt remains
|
||||
separate from this read-only RPC verification.
|
||||
|
||||
## Combined qualification after resumed integration
|
||||
|
||||
The full isolated backend rerun passed 1,848 tests with zero failures and five
|
||||
existing skips. All 385 recorded source, build and fixture hashes remained
|
||||
unchanged. Evidence: `/tmp/archy-qualified-candidate-backend-rerun-tests.log` and
|
||||
`/tmp/archy-qualified-candidate-backend-rerun-provenance.json`. Earlier failed
|
||||
runs remain recorded. This qualifies the current backend primitives and Browse
|
||||
path repair locally; production build and live deployment checks are next.
|
||||
Complete purchase callers, app registration/publication and timed playback
|
||||
acceptance remain open. No real payment or public publication was performed.
|
||||
|
||||
Reference in New Issue
Block a user