@qlever-llc/trellis 0.8.4 → 0.9.0-rc.10
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 +1 -1
- package/bin/trellis-generate.js +0 -0
- package/esm/auth/browser/login.d.ts.map +1 -1
- package/esm/auth/browser/login.js +46 -3
- package/esm/auth/browser/portal.d.ts.map +1 -1
- package/esm/auth/browser/portal.js +5 -1
- package/esm/auth/browser/session.d.ts +18 -7
- package/esm/auth/browser/session.d.ts.map +1 -1
- package/esm/auth/browser/session.js +47 -11
- package/esm/auth/browser/storage.d.ts +6 -1
- package/esm/auth/browser/storage.d.ts.map +1 -1
- package/esm/auth/browser/storage.js +15 -3
- package/esm/auth/browser.d.ts +2 -2
- package/esm/auth/browser.d.ts.map +1 -1
- package/esm/auth/browser.js +1 -1
- package/esm/auth/device_activation.d.ts +36 -33
- package/esm/auth/device_activation.d.ts.map +1 -1
- package/esm/auth/device_activation.js +26 -22
- package/esm/auth/mod.d.ts +4 -4
- package/esm/auth/mod.d.ts.map +1 -1
- package/esm/auth/mod.js +2 -2
- package/esm/auth/proof.d.ts +3 -1
- package/esm/auth/proof.d.ts.map +1 -1
- package/esm/auth/proof.js +21 -15
- package/esm/auth/protocol.d.ts +2457 -941
- package/esm/auth/protocol.d.ts.map +1 -1
- package/esm/auth/protocol.js +747 -375
- package/esm/auth/schemas.d.ts +25 -4
- package/esm/auth/schemas.d.ts.map +1 -1
- package/esm/auth/schemas.js +14 -4
- package/esm/auth/session_auth.d.ts +1 -1
- package/esm/auth/session_auth.d.ts.map +1 -1
- package/esm/auth/session_auth.js +7 -1
- package/esm/client_connect.d.ts +2 -0
- package/esm/client_connect.d.ts.map +1 -1
- package/esm/client_connect.js +76 -15
- package/esm/contract.d.ts +3 -0
- package/esm/contract.d.ts.map +1 -1
- package/esm/contract_support/mod.d.ts +422 -43
- package/esm/contract_support/mod.d.ts.map +1 -1
- package/esm/contract_support/mod.js +734 -33
- package/esm/contract_support/protocol.d.ts +20 -5
- package/esm/contract_support/protocol.d.ts.map +1 -1
- package/esm/contract_support/protocol.js +18 -10
- package/esm/contract_support/runtime.d.ts +11 -0
- package/esm/contract_support/runtime.d.ts.map +1 -1
- package/esm/contract_support/schema_pointers.d.ts.map +1 -1
- package/esm/contract_support/schema_pointers.js +32 -14
- package/esm/device.d.ts +2 -0
- package/esm/device.d.ts.map +1 -1
- package/esm/device.js +3 -0
- package/esm/errors/AuthError.d.ts +2 -1
- package/esm/errors/AuthError.d.ts.map +1 -1
- package/esm/errors/AuthError.js +8 -3
- package/esm/errors/index.d.ts +4 -4
- package/esm/errors/index.d.ts.map +1 -1
- package/esm/errors/index.js +1 -0
- package/esm/generated-sdk/auth/api.d.ts +27 -9
- package/esm/generated-sdk/auth/api.d.ts.map +1 -1
- package/esm/generated-sdk/auth/api.js +16 -590
- package/esm/generated-sdk/auth/client.d.ts +91 -85
- package/esm/generated-sdk/auth/client.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.d.ts +1 -1
- package/esm/generated-sdk/auth/contract.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.js +4 -2
- package/esm/generated-sdk/auth/mod.d.ts +1 -0
- package/esm/generated-sdk/auth/mod.d.ts.map +1 -1
- package/esm/generated-sdk/auth/owned_api.d.ts +3 -0
- package/esm/generated-sdk/auth/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/auth/owned_api.js +594 -0
- package/esm/generated-sdk/auth/schemas.d.ts +9959 -5160
- package/esm/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/auth/schemas.js +136 -137
- package/esm/generated-sdk/auth/types.d.ts +2418 -1557
- package/esm/generated-sdk/auth/types.d.ts.map +1 -1
- package/esm/generated-sdk/auth/types.js +1 -1
- package/esm/generated-sdk/health/api.d.ts +24 -9
- package/esm/generated-sdk/health/api.d.ts.map +1 -1
- package/esm/generated-sdk/health/api.js +12 -20
- package/esm/generated-sdk/health/client.d.ts +2 -1
- package/esm/generated-sdk/health/client.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.js +2 -0
- package/esm/generated-sdk/health/owned_api.d.ts +3 -0
- package/esm/generated-sdk/health/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/health/owned_api.js +16 -0
- package/esm/generated-sdk/health/types.d.ts +2 -0
- package/esm/generated-sdk/health/types.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/api.d.ts +33 -9
- package/esm/generated-sdk/jobs/api.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/api.js +22 -87
- package/esm/generated-sdk/jobs/client.d.ts +9 -2
- package/esm/generated-sdk/jobs/client.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.d.ts +1 -1
- package/esm/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.js +4 -2
- package/esm/generated-sdk/jobs/owned_api.d.ts +3 -0
- package/esm/generated-sdk/jobs/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/jobs/owned_api.js +118 -0
- package/esm/generated-sdk/jobs/schemas.d.ts +336 -123
- package/esm/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/schemas.js +17 -15
- package/esm/generated-sdk/jobs/types.d.ts +144 -34
- package/esm/generated-sdk/jobs/types.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/types.js +36 -1
- package/esm/generated-sdk/state/api.d.ts +27 -9
- package/esm/generated-sdk/state/api.d.ts.map +1 -1
- package/esm/generated-sdk/state/api.js +16 -71
- package/esm/generated-sdk/state/client.d.ts +4 -2
- package/esm/generated-sdk/state/client.d.ts.map +1 -1
- package/esm/generated-sdk/state/contract.d.ts +1 -1
- package/esm/generated-sdk/state/contract.d.ts.map +1 -1
- package/esm/generated-sdk/state/contract.js +4 -2
- package/esm/generated-sdk/state/owned_api.d.ts +3 -0
- package/esm/generated-sdk/state/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/state/owned_api.js +66 -0
- package/esm/generated-sdk/state/schemas.d.ts +264 -284
- package/esm/generated-sdk/state/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/state/schemas.js +6 -6
- package/esm/generated-sdk/state/types.d.ts +24 -23
- package/esm/generated-sdk/state/types.d.ts.map +1 -1
- package/esm/generated-sdk/state/types.js +1 -1
- package/esm/generated-sdk/trellis-core/api.d.ts +27 -9
- package/esm/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/api.js +16 -39
- package/esm/generated-sdk/trellis-core/client.d.ts +5 -2
- package/esm/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.js +4 -2
- package/esm/generated-sdk/trellis-core/owned_api.d.ts +3 -0
- package/esm/generated-sdk/trellis-core/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/trellis-core/owned_api.js +42 -0
- package/esm/generated-sdk/trellis-core/schemas.d.ts +259 -11
- package/esm/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/schemas.js +5 -3
- package/esm/generated-sdk/trellis-core/types.d.ts +56 -1
- package/esm/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/types.js +1 -1
- package/esm/helpers.d.ts.map +1 -1
- package/esm/index.d.ts +4 -3
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/jobs.d.ts +10 -1
- package/esm/jobs.d.ts.map +1 -1
- package/esm/jobs.js +16 -1
- package/esm/kv.d.ts.map +1 -1
- package/esm/kv.js +10 -4
- package/esm/models/auth/rpc/Logout.d.ts +4 -4
- package/esm/models/auth/rpc/Logout.d.ts.map +1 -1
- package/esm/models/auth/rpc/Logout.js +2 -2
- package/esm/models/trellis/Page.d.ts +2 -0
- package/esm/models/trellis/Page.d.ts.map +1 -0
- package/esm/models/trellis/Page.js +1 -0
- package/esm/models/trellis/State.d.ts +1 -0
- package/esm/models/trellis/State.d.ts.map +1 -1
- package/esm/models/trellis/State.js +1 -0
- package/esm/models/trellis/rpc/StateList.d.ts +9 -12
- package/esm/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/esm/models/trellis/rpc/StateList.js +16 -18
- package/esm/npm/src/auth/browser/login.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/login.js +46 -3
- package/esm/npm/src/auth/browser/portal.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/portal.js +5 -1
- package/esm/npm/src/auth/browser/session.d.ts +18 -7
- package/esm/npm/src/auth/browser/session.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/session.js +47 -11
- package/esm/npm/src/auth/browser/storage.d.ts +6 -1
- package/esm/npm/src/auth/browser/storage.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/storage.js +15 -3
- package/esm/npm/src/auth/browser.d.ts +2 -2
- package/esm/npm/src/auth/browser.d.ts.map +1 -1
- package/esm/npm/src/auth/browser.js +1 -1
- package/esm/npm/src/auth/device_activation.d.ts +36 -33
- package/esm/npm/src/auth/device_activation.d.ts.map +1 -1
- package/esm/npm/src/auth/device_activation.js +26 -22
- package/esm/npm/src/auth/mod.d.ts +4 -4
- package/esm/npm/src/auth/mod.d.ts.map +1 -1
- package/esm/npm/src/auth/mod.js +2 -2
- package/esm/npm/src/auth/proof.d.ts +3 -1
- package/esm/npm/src/auth/proof.d.ts.map +1 -1
- package/esm/npm/src/auth/proof.js +21 -15
- package/esm/npm/src/auth/protocol.d.ts +2457 -941
- package/esm/npm/src/auth/protocol.d.ts.map +1 -1
- package/esm/npm/src/auth/protocol.js +747 -375
- package/esm/npm/src/auth/schemas.d.ts +25 -4
- package/esm/npm/src/auth/schemas.d.ts.map +1 -1
- package/esm/npm/src/auth/schemas.js +14 -4
- package/esm/npm/src/auth/session_auth.d.ts +1 -1
- package/esm/npm/src/auth/session_auth.d.ts.map +1 -1
- package/esm/npm/src/auth/session_auth.js +7 -1
- package/esm/npm/src/client_connect.d.ts +2 -0
- package/esm/npm/src/client_connect.d.ts.map +1 -1
- package/esm/npm/src/client_connect.js +76 -15
- package/esm/npm/src/contract.d.ts +3 -0
- package/esm/npm/src/contract.d.ts.map +1 -1
- package/esm/npm/src/contract_support/mod.d.ts +422 -43
- package/esm/npm/src/contract_support/mod.d.ts.map +1 -1
- package/esm/npm/src/contract_support/mod.js +734 -33
- package/esm/npm/src/contract_support/protocol.d.ts +20 -5
- package/esm/npm/src/contract_support/protocol.d.ts.map +1 -1
- package/esm/npm/src/contract_support/protocol.js +18 -10
- package/esm/npm/src/contract_support/runtime.d.ts +11 -0
- package/esm/npm/src/contract_support/runtime.d.ts.map +1 -1
- package/esm/npm/src/contract_support/schema_pointers.d.ts.map +1 -1
- package/esm/npm/src/contract_support/schema_pointers.js +32 -14
- package/esm/npm/src/device/deno.d.ts.map +1 -1
- package/esm/npm/src/device/deno.js +6 -0
- package/esm/npm/src/device.d.ts +2 -0
- package/esm/npm/src/device.d.ts.map +1 -1
- package/esm/npm/src/device.js +3 -0
- package/esm/npm/src/errors/AuthError.d.ts +2 -1
- package/esm/npm/src/errors/AuthError.d.ts.map +1 -1
- package/esm/npm/src/errors/AuthError.js +8 -3
- package/esm/npm/src/errors/index.d.ts +4 -4
- package/esm/npm/src/errors/index.d.ts.map +1 -1
- package/esm/npm/src/errors/index.js +1 -0
- package/esm/npm/src/generate.js +39 -26
- package/esm/npm/src/helpers.d.ts.map +1 -1
- package/esm/npm/src/index.d.ts +4 -3
- package/esm/npm/src/index.d.ts.map +1 -1
- package/esm/npm/src/index.js +1 -0
- package/esm/npm/src/jobs.d.ts +10 -1
- package/esm/npm/src/jobs.d.ts.map +1 -1
- package/esm/npm/src/jobs.js +16 -1
- package/esm/npm/src/kv.d.ts.map +1 -1
- package/esm/npm/src/kv.js +10 -4
- package/esm/npm/src/models/auth/rpc/Logout.d.ts +4 -4
- package/esm/npm/src/models/auth/rpc/Logout.d.ts.map +1 -1
- package/esm/npm/src/models/auth/rpc/Logout.js +2 -2
- package/esm/npm/src/models/trellis/Page.d.ts +2 -0
- package/esm/npm/src/models/trellis/Page.d.ts.map +1 -0
- package/esm/npm/src/models/trellis/Page.js +1 -0
- package/esm/npm/src/models/trellis/State.d.ts +1 -0
- package/esm/npm/src/models/trellis/State.d.ts.map +1 -1
- package/esm/npm/src/models/trellis/State.js +1 -0
- package/esm/npm/src/models/trellis/rpc/StateList.d.ts +9 -12
- package/esm/npm/src/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/esm/npm/src/models/trellis/rpc/StateList.js +16 -18
- package/esm/npm/src/operations.d.ts +16 -7
- package/esm/npm/src/operations.d.ts.map +1 -1
- package/esm/npm/src/operations.js +84 -19
- package/esm/npm/src/runtime_transport.d.ts +2 -0
- package/esm/npm/src/runtime_transport.d.ts.map +1 -1
- package/esm/npm/src/runtime_transport.js +1 -0
- package/esm/npm/src/server/internal_jobs/active-job.d.ts +2 -1
- package/esm/npm/src/server/internal_jobs/active-job.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/active-job.js +3 -0
- package/esm/npm/src/server/internal_jobs/job-manager.d.ts +4 -1
- package/esm/npm/src/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/job-manager.js +61 -1
- package/esm/npm/src/server/internal_jobs/projection.js +1 -0
- package/esm/npm/src/server/internal_jobs/runtime-worker.d.ts +13 -1
- package/esm/npm/src/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/runtime-worker.js +73 -13
- package/esm/npm/src/server/internal_jobs/types.d.ts +19 -0
- package/esm/npm/src/server/internal_jobs/types.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/types.js +10 -0
- package/esm/npm/src/server/runtime.d.ts +1 -0
- package/esm/npm/src/server/runtime.d.ts.map +1 -1
- package/esm/npm/src/server/service.d.ts +10 -1
- package/esm/npm/src/server/service.d.ts.map +1 -1
- package/esm/npm/src/server/service.js +210 -64
- package/esm/npm/src/server/transfer.d.ts.map +1 -1
- package/esm/npm/src/server/transfer.js +4 -0
- package/esm/npm/src/server.d.ts.map +1 -1
- package/esm/npm/src/server.js +337 -34
- package/esm/npm/src/store.d.ts +8 -1
- package/esm/npm/src/store.d.ts.map +1 -1
- package/esm/npm/src/store.js +46 -8
- package/esm/npm/src/transfer.d.ts +3 -0
- package/esm/npm/src/transfer.d.ts.map +1 -1
- package/esm/npm/src/transfer.js +20 -30
- package/esm/npm/src/trellis.d.ts +85 -22
- package/esm/npm/src/trellis.d.ts.map +1 -1
- package/esm/npm/src/trellis.js +525 -61
- package/esm/operations.d.ts +16 -7
- package/esm/operations.d.ts.map +1 -1
- package/esm/operations.js +84 -19
- package/esm/runtime_transport.d.ts +2 -0
- package/esm/runtime_transport.d.ts.map +1 -1
- package/esm/runtime_transport.js +1 -0
- package/esm/store.d.ts +8 -1
- package/esm/store.d.ts.map +1 -1
- package/esm/store.js +46 -8
- package/esm/transfer.d.ts +3 -0
- package/esm/transfer.d.ts.map +1 -1
- package/esm/transfer.js +20 -30
- package/esm/trellis.d.ts +85 -22
- package/esm/trellis.d.ts.map +1 -1
- package/esm/trellis.js +525 -61
- package/package.json +6 -3
- package/script/auth/browser/login.d.ts.map +1 -1
- package/script/auth/browser/login.js +46 -3
- package/script/auth/browser/portal.d.ts.map +1 -1
- package/script/auth/browser/portal.js +5 -1
- package/script/auth/browser/session.d.ts +18 -7
- package/script/auth/browser/session.d.ts.map +1 -1
- package/script/auth/browser/session.js +47 -11
- package/script/auth/browser/storage.d.ts +6 -1
- package/script/auth/browser/storage.d.ts.map +1 -1
- package/script/auth/browser/storage.js +15 -3
- package/script/auth/browser.d.ts +2 -2
- package/script/auth/browser.d.ts.map +1 -1
- package/script/auth/browser.js +2 -1
- package/script/auth/device_activation.d.ts +36 -33
- package/script/auth/device_activation.d.ts.map +1 -1
- package/script/auth/device_activation.js +25 -21
- package/script/auth/mod.d.ts +4 -4
- package/script/auth/mod.d.ts.map +1 -1
- package/script/auth/mod.js +132 -137
- package/script/auth/proof.d.ts +3 -1
- package/script/auth/proof.d.ts.map +1 -1
- package/script/auth/proof.js +21 -15
- package/script/auth/protocol.d.ts +2457 -941
- package/script/auth/protocol.d.ts.map +1 -1
- package/script/auth/protocol.js +749 -377
- package/script/auth/schemas.d.ts +25 -4
- package/script/auth/schemas.d.ts.map +1 -1
- package/script/auth/schemas.js +16 -5
- package/script/auth/session_auth.d.ts +1 -1
- package/script/auth/session_auth.d.ts.map +1 -1
- package/script/auth/session_auth.js +7 -1
- package/script/client_connect.d.ts +2 -0
- package/script/client_connect.d.ts.map +1 -1
- package/script/client_connect.js +76 -15
- package/script/contract.d.ts +3 -0
- package/script/contract.d.ts.map +1 -1
- package/script/contract_support/mod.d.ts +422 -43
- package/script/contract_support/mod.d.ts.map +1 -1
- package/script/contract_support/mod.js +757 -51
- package/script/contract_support/protocol.d.ts +20 -5
- package/script/contract_support/protocol.d.ts.map +1 -1
- package/script/contract_support/protocol.js +20 -11
- package/script/contract_support/runtime.d.ts +11 -0
- package/script/contract_support/runtime.d.ts.map +1 -1
- package/script/contract_support/schema_pointers.d.ts.map +1 -1
- package/script/contract_support/schema_pointers.js +32 -14
- package/script/device.d.ts +2 -0
- package/script/device.d.ts.map +1 -1
- package/script/device.js +3 -0
- package/script/errors/AuthError.d.ts +2 -1
- package/script/errors/AuthError.d.ts.map +1 -1
- package/script/errors/AuthError.js +8 -3
- package/script/errors/index.d.ts +4 -4
- package/script/errors/index.d.ts.map +1 -1
- package/script/errors/index.js +1 -0
- package/script/generated-sdk/auth/api.d.ts +27 -9
- package/script/generated-sdk/auth/api.d.ts.map +1 -1
- package/script/generated-sdk/auth/api.js +17 -591
- package/script/generated-sdk/auth/client.d.ts +91 -85
- package/script/generated-sdk/auth/client.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.d.ts +1 -1
- package/script/generated-sdk/auth/contract.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.js +4 -2
- package/script/generated-sdk/auth/mod.d.ts +1 -0
- package/script/generated-sdk/auth/mod.d.ts.map +1 -1
- package/script/generated-sdk/auth/owned_api.d.ts +3 -0
- package/script/generated-sdk/auth/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/auth/owned_api.js +597 -0
- package/script/generated-sdk/auth/schemas.d.ts +9959 -5160
- package/script/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/script/generated-sdk/auth/schemas.js +139 -140
- package/script/generated-sdk/auth/types.d.ts +2418 -1557
- package/script/generated-sdk/auth/types.d.ts.map +1 -1
- package/script/generated-sdk/auth/types.js +1 -1
- package/script/generated-sdk/health/api.d.ts +24 -9
- package/script/generated-sdk/health/api.d.ts.map +1 -1
- package/script/generated-sdk/health/api.js +13 -21
- package/script/generated-sdk/health/client.d.ts +2 -1
- package/script/generated-sdk/health/client.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.js +2 -0
- package/script/generated-sdk/health/owned_api.d.ts +3 -0
- package/script/generated-sdk/health/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/health/owned_api.js +19 -0
- package/script/generated-sdk/health/types.d.ts +2 -0
- package/script/generated-sdk/health/types.d.ts.map +1 -1
- package/script/generated-sdk/jobs/api.d.ts +33 -9
- package/script/generated-sdk/jobs/api.d.ts.map +1 -1
- package/script/generated-sdk/jobs/api.js +23 -88
- package/script/generated-sdk/jobs/client.d.ts +9 -2
- package/script/generated-sdk/jobs/client.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.d.ts +1 -1
- package/script/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.js +4 -2
- package/script/generated-sdk/jobs/owned_api.d.ts +3 -0
- package/script/generated-sdk/jobs/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/jobs/owned_api.js +154 -0
- package/script/generated-sdk/jobs/schemas.d.ts +336 -123
- package/script/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/script/generated-sdk/jobs/schemas.js +18 -16
- package/script/generated-sdk/jobs/types.d.ts +144 -34
- package/script/generated-sdk/jobs/types.d.ts.map +1 -1
- package/script/generated-sdk/jobs/types.js +38 -2
- package/script/generated-sdk/state/api.d.ts +27 -9
- package/script/generated-sdk/state/api.d.ts.map +1 -1
- package/script/generated-sdk/state/api.js +17 -72
- package/script/generated-sdk/state/client.d.ts +4 -2
- package/script/generated-sdk/state/client.d.ts.map +1 -1
- package/script/generated-sdk/state/contract.d.ts +1 -1
- package/script/generated-sdk/state/contract.d.ts.map +1 -1
- package/script/generated-sdk/state/contract.js +4 -2
- package/script/generated-sdk/state/owned_api.d.ts +3 -0
- package/script/generated-sdk/state/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/state/owned_api.js +69 -0
- package/script/generated-sdk/state/schemas.d.ts +264 -284
- package/script/generated-sdk/state/schemas.d.ts.map +1 -1
- package/script/generated-sdk/state/schemas.js +6 -6
- package/script/generated-sdk/state/types.d.ts +24 -23
- package/script/generated-sdk/state/types.d.ts.map +1 -1
- package/script/generated-sdk/state/types.js +1 -1
- package/script/generated-sdk/trellis-core/api.d.ts +27 -9
- package/script/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/api.js +17 -40
- package/script/generated-sdk/trellis-core/client.d.ts +5 -2
- package/script/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.js +4 -2
- package/script/generated-sdk/trellis-core/owned_api.d.ts +3 -0
- package/script/generated-sdk/trellis-core/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/trellis-core/owned_api.js +45 -0
- package/script/generated-sdk/trellis-core/schemas.d.ts +259 -11
- package/script/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/schemas.js +6 -4
- package/script/generated-sdk/trellis-core/types.d.ts +56 -1
- package/script/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/types.js +1 -1
- package/script/helpers.d.ts.map +1 -1
- package/script/index.d.ts +4 -3
- package/script/index.d.ts.map +1 -1
- package/script/index.js +5 -2
- package/script/jobs.d.ts +10 -1
- package/script/jobs.d.ts.map +1 -1
- package/script/jobs.js +17 -2
- package/script/kv.d.ts.map +1 -1
- package/script/kv.js +10 -4
- package/script/models/auth/rpc/Logout.d.ts +4 -4
- package/script/models/auth/rpc/Logout.d.ts.map +1 -1
- package/script/models/auth/rpc/Logout.js +3 -3
- package/script/models/trellis/Page.d.ts +2 -0
- package/script/models/trellis/Page.d.ts.map +1 -0
- package/script/models/trellis/Page.js +6 -0
- package/script/models/trellis/State.d.ts +1 -0
- package/script/models/trellis/State.d.ts.map +1 -1
- package/script/models/trellis/State.js +1 -0
- package/script/models/trellis/rpc/StateList.d.ts +9 -12
- package/script/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/script/models/trellis/rpc/StateList.js +16 -18
- package/script/npm/src/auth/browser/login.d.ts.map +1 -1
- package/script/npm/src/auth/browser/login.js +46 -3
- package/script/npm/src/auth/browser/portal.d.ts.map +1 -1
- package/script/npm/src/auth/browser/portal.js +5 -1
- package/script/npm/src/auth/browser/session.d.ts +18 -7
- package/script/npm/src/auth/browser/session.d.ts.map +1 -1
- package/script/npm/src/auth/browser/session.js +47 -11
- package/script/npm/src/auth/browser/storage.d.ts +6 -1
- package/script/npm/src/auth/browser/storage.d.ts.map +1 -1
- package/script/npm/src/auth/browser/storage.js +15 -3
- package/script/npm/src/auth/browser.d.ts +2 -2
- package/script/npm/src/auth/browser.d.ts.map +1 -1
- package/script/npm/src/auth/browser.js +2 -1
- package/script/npm/src/auth/device_activation.d.ts +36 -33
- package/script/npm/src/auth/device_activation.d.ts.map +1 -1
- package/script/npm/src/auth/device_activation.js +25 -21
- package/script/npm/src/auth/mod.d.ts +4 -4
- package/script/npm/src/auth/mod.d.ts.map +1 -1
- package/script/npm/src/auth/mod.js +132 -137
- package/script/npm/src/auth/proof.d.ts +3 -1
- package/script/npm/src/auth/proof.d.ts.map +1 -1
- package/script/npm/src/auth/proof.js +21 -15
- package/script/npm/src/auth/protocol.d.ts +2457 -941
- package/script/npm/src/auth/protocol.d.ts.map +1 -1
- package/script/npm/src/auth/protocol.js +749 -377
- package/script/npm/src/auth/schemas.d.ts +25 -4
- package/script/npm/src/auth/schemas.d.ts.map +1 -1
- package/script/npm/src/auth/schemas.js +16 -5
- package/script/npm/src/auth/session_auth.d.ts +1 -1
- package/script/npm/src/auth/session_auth.d.ts.map +1 -1
- package/script/npm/src/auth/session_auth.js +7 -1
- package/script/npm/src/client_connect.d.ts +2 -0
- package/script/npm/src/client_connect.d.ts.map +1 -1
- package/script/npm/src/client_connect.js +76 -15
- package/script/npm/src/contract.d.ts +3 -0
- package/script/npm/src/contract.d.ts.map +1 -1
- package/script/npm/src/contract_support/mod.d.ts +422 -43
- package/script/npm/src/contract_support/mod.d.ts.map +1 -1
- package/script/npm/src/contract_support/mod.js +757 -51
- package/script/npm/src/contract_support/protocol.d.ts +20 -5
- package/script/npm/src/contract_support/protocol.d.ts.map +1 -1
- package/script/npm/src/contract_support/protocol.js +20 -11
- package/script/npm/src/contract_support/runtime.d.ts +11 -0
- package/script/npm/src/contract_support/runtime.d.ts.map +1 -1
- package/script/npm/src/contract_support/schema_pointers.d.ts.map +1 -1
- package/script/npm/src/contract_support/schema_pointers.js +32 -14
- package/script/npm/src/device/deno.d.ts.map +1 -1
- package/script/npm/src/device/deno.js +6 -0
- package/script/npm/src/device.d.ts +2 -0
- package/script/npm/src/device.d.ts.map +1 -1
- package/script/npm/src/device.js +3 -0
- package/script/npm/src/errors/AuthError.d.ts +2 -1
- package/script/npm/src/errors/AuthError.d.ts.map +1 -1
- package/script/npm/src/errors/AuthError.js +8 -3
- package/script/npm/src/errors/index.d.ts +4 -4
- package/script/npm/src/errors/index.d.ts.map +1 -1
- package/script/npm/src/errors/index.js +1 -0
- package/script/npm/src/generate.js +39 -59
- package/script/npm/src/helpers.d.ts.map +1 -1
- package/script/npm/src/index.d.ts +4 -3
- package/script/npm/src/index.d.ts.map +1 -1
- package/script/npm/src/index.js +5 -2
- package/script/npm/src/jobs.d.ts +10 -1
- package/script/npm/src/jobs.d.ts.map +1 -1
- package/script/npm/src/jobs.js +17 -2
- package/script/npm/src/kv.d.ts.map +1 -1
- package/script/npm/src/kv.js +10 -4
- package/script/npm/src/models/auth/rpc/Logout.d.ts +4 -4
- package/script/npm/src/models/auth/rpc/Logout.d.ts.map +1 -1
- package/script/npm/src/models/auth/rpc/Logout.js +3 -3
- package/script/npm/src/models/trellis/Page.d.ts +2 -0
- package/script/npm/src/models/trellis/Page.d.ts.map +1 -0
- package/script/npm/src/models/trellis/Page.js +6 -0
- package/script/npm/src/models/trellis/State.d.ts +1 -0
- package/script/npm/src/models/trellis/State.d.ts.map +1 -1
- package/script/npm/src/models/trellis/State.js +1 -0
- package/script/npm/src/models/trellis/rpc/StateList.d.ts +9 -12
- package/script/npm/src/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/script/npm/src/models/trellis/rpc/StateList.js +16 -18
- package/script/npm/src/operations.d.ts +16 -7
- package/script/npm/src/operations.d.ts.map +1 -1
- package/script/npm/src/operations.js +84 -19
- package/script/npm/src/runtime_transport.d.ts +2 -0
- package/script/npm/src/runtime_transport.d.ts.map +1 -1
- package/script/npm/src/runtime_transport.js +2 -1
- package/script/npm/src/server/internal_jobs/active-job.d.ts +2 -1
- package/script/npm/src/server/internal_jobs/active-job.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/active-job.js +3 -0
- package/script/npm/src/server/internal_jobs/job-manager.d.ts +4 -1
- package/script/npm/src/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/job-manager.js +61 -1
- package/script/npm/src/server/internal_jobs/projection.js +1 -0
- package/script/npm/src/server/internal_jobs/runtime-worker.d.ts +13 -1
- package/script/npm/src/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/runtime-worker.js +74 -13
- package/script/npm/src/server/internal_jobs/types.d.ts +19 -0
- package/script/npm/src/server/internal_jobs/types.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/types.js +11 -1
- package/script/npm/src/server/runtime.d.ts +1 -0
- package/script/npm/src/server/runtime.d.ts.map +1 -1
- package/script/npm/src/server/service.d.ts +10 -1
- package/script/npm/src/server/service.d.ts.map +1 -1
- package/script/npm/src/server/service.js +208 -62
- package/script/npm/src/server/transfer.d.ts.map +1 -1
- package/script/npm/src/server/transfer.js +4 -0
- package/script/npm/src/server.d.ts.map +1 -1
- package/script/npm/src/server.js +336 -33
- package/script/npm/src/store.d.ts +8 -1
- package/script/npm/src/store.d.ts.map +1 -1
- package/script/npm/src/store.js +46 -8
- package/script/npm/src/transfer.d.ts +3 -0
- package/script/npm/src/transfer.d.ts.map +1 -1
- package/script/npm/src/transfer.js +19 -29
- package/script/npm/src/trellis.d.ts +85 -22
- package/script/npm/src/trellis.d.ts.map +1 -1
- package/script/npm/src/trellis.js +525 -61
- package/script/operations.d.ts +16 -7
- package/script/operations.d.ts.map +1 -1
- package/script/operations.js +84 -19
- package/script/runtime_transport.d.ts +2 -0
- package/script/runtime_transport.d.ts.map +1 -1
- package/script/runtime_transport.js +2 -1
- package/script/store.d.ts +8 -1
- package/script/store.d.ts.map +1 -1
- package/script/store.js +46 -8
- package/script/transfer.d.ts +3 -0
- package/script/transfer.d.ts.map +1 -1
- package/script/transfer.js +19 -29
- package/script/trellis.d.ts +85 -22
- package/script/trellis.d.ts.map +1 -1
- package/script/trellis.js +525 -61
- package/src/_dnt.polyfills.ts +274 -0
- package/src/_dnt.shims.ts +64 -0
- package/src/auth/browser/login.ts +295 -0
- package/src/auth/browser/portal.ts +75 -0
- package/src/auth/browser/session.ts +197 -0
- package/src/auth/browser/storage.ts +105 -0
- package/src/auth/browser.ts +82 -0
- package/src/auth/device_activation.ts +715 -0
- package/src/auth/keys.ts +116 -0
- package/src/auth/mod.ts +298 -0
- package/src/auth/proof.ts +111 -0
- package/src/auth/protocol.ts +1629 -0
- package/src/auth/schemas.ts +145 -0
- package/src/auth/session_auth.ts +167 -0
- package/src/auth/time.ts +15 -0
- package/src/auth/trellis_id.ts +9 -0
- package/src/auth/types.ts +4 -0
- package/src/auth/utils.ts +87 -0
- package/src/auth.ts +2 -0
- package/src/browser.ts +8 -0
- package/src/client.ts +164 -0
- package/src/client_connect.ts +1328 -0
- package/src/codec.ts +107 -0
- package/src/connection.ts +466 -0
- package/src/contract.ts +84 -0
- package/src/contract_support/canonical.ts +217 -0
- package/src/contract_support/mod.ts +5079 -0
- package/src/contract_support/protocol.ts +213 -0
- package/src/contract_support/runtime.ts +129 -0
- package/src/contract_support/schema_pointers.ts +161 -0
- package/src/contracts.ts +9 -0
- package/src/device/deno.ts +941 -0
- package/src/device.ts +989 -0
- package/src/env.ts +1 -0
- package/src/errors/AuthError.ts +82 -0
- package/src/errors/KVError.ts +47 -0
- package/src/errors/RemoteError.ts +111 -0
- package/src/errors/StoreError.ts +43 -0
- package/src/errors/TransferError.ts +43 -0
- package/src/errors/TransportError.ts +48 -0
- package/src/errors/TrellisError.ts +20 -0
- package/src/errors/ValidationError.ts +80 -0
- package/src/errors/index.ts +195 -0
- package/src/generate.ts +329 -0
- package/src/globals.ts +26 -0
- package/src/health.ts +28 -0
- package/src/helpers.ts +63 -0
- package/src/host/mod.ts +9 -0
- package/src/host/node.ts +9 -0
- package/src/index.ts +233 -0
- package/src/jobs.ts +344 -0
- package/src/kv.ts +564 -0
- package/src/models/auth/rpc/Logout.ts +15 -0
- package/src/models/trellis/Page.ts +6 -0
- package/src/models/trellis/State.ts +55 -0
- package/src/models/trellis/TrellisError.ts +21 -0
- package/src/models/trellis/rpc/StateDelete.ts +13 -0
- package/src/models/trellis/rpc/StateGet.ts +25 -0
- package/src/models/trellis/rpc/StateList.ts +26 -0
- package/src/models/trellis/rpc/StatePut.ts +42 -0
- package/src/operations.ts +1508 -0
- package/src/runtime_transport.ts +132 -0
- package/src/sdk/auth.ts +2 -0
- package/src/sdk/core.ts +2 -0
- package/src/sdk/health.ts +2 -0
- package/src/sdk/jobs.ts +2 -0
- package/src/sdk/state.ts +2 -0
- package/src/server/health.ts +379 -0
- package/src/server/health_rpc.ts +51 -0
- package/src/server/health_schemas.ts +61 -0
- package/src/server/internal_jobs/active-job.ts +115 -0
- package/src/server/internal_jobs/bindings.ts +26 -0
- package/src/server/internal_jobs/cancellation-registry.ts +71 -0
- package/src/server/internal_jobs/heartbeat.ts +120 -0
- package/src/server/internal_jobs/job-manager.ts +456 -0
- package/src/server/internal_jobs/projection.ts +48 -0
- package/src/server/internal_jobs/runtime-worker.ts +741 -0
- package/src/server/internal_jobs/types.ts +124 -0
- package/src/server/runtime.ts +27 -0
- package/src/server/service.ts +2377 -0
- package/src/server/subscription.ts +143 -0
- package/src/server/transfer.ts +962 -0
- package/src/server.ts +1725 -0
- package/src/server_logger.ts +10 -0
- package/src/service/deno.ts +18 -0
- package/src/service/mod.ts +68 -0
- package/src/service/node.ts +18 -0
- package/src/store.ts +658 -0
- package/src/tasks.ts +34 -0
- package/src/telemetry/carrier.ts +35 -0
- package/src/telemetry/core.ts +31 -0
- package/src/telemetry/env.ts +23 -0
- package/src/telemetry/mod.ts +26 -0
- package/src/telemetry/nats.ts +15 -0
- package/src/telemetry/result.ts +20 -0
- package/src/telemetry/trace.ts +39 -0
- package/src/telemetry/trellis.ts +1 -0
- package/src/tracing.ts +28 -0
- package/src/transfer.ts +602 -0
- package/src/trellis.ts +3650 -0
- package/esm/models/trellis/Paginate.d.ts +0 -7
- package/esm/models/trellis/Paginate.d.ts.map +0 -1
- package/esm/models/trellis/Paginate.js +0 -5
- package/esm/npm/src/models/trellis/Paginate.d.ts +0 -7
- package/esm/npm/src/models/trellis/Paginate.d.ts.map +0 -1
- package/esm/npm/src/models/trellis/Paginate.js +0 -5
- package/script/models/trellis/Paginate.d.ts +0 -7
- package/script/models/trellis/Paginate.d.ts.map +0 -1
- package/script/models/trellis/Paginate.js +0 -11
- package/script/npm/src/models/trellis/Paginate.d.ts +0 -7
- package/script/npm/src/models/trellis/Paginate.d.ts.map +0 -1
- package/script/npm/src/models/trellis/Paginate.js +0 -11
package/src/device.ts
ADDED
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
import "./_dnt.polyfills.js";
|
|
2
|
+
import {
|
|
3
|
+
type Authenticator,
|
|
4
|
+
jwtAuthenticator,
|
|
5
|
+
type NatsConnection,
|
|
6
|
+
} from "@nats-io/nats-core";
|
|
7
|
+
import {
|
|
8
|
+
AsyncResult,
|
|
9
|
+
type BaseError,
|
|
10
|
+
Result,
|
|
11
|
+
UnexpectedError,
|
|
12
|
+
} from "@qlever-llc/result";
|
|
13
|
+
import {
|
|
14
|
+
CONTRACT_STATE_METADATA,
|
|
15
|
+
type ContractStateMetadata,
|
|
16
|
+
} from "./contract_support/mod.js";
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
buildDeviceActivationPayload,
|
|
20
|
+
deriveDeviceIdentity,
|
|
21
|
+
signDeviceWaitRequest,
|
|
22
|
+
startDeviceActivationRequest,
|
|
23
|
+
verifyDeviceConfirmationCode,
|
|
24
|
+
waitForDeviceActivation,
|
|
25
|
+
} from "./auth/device_activation.js";
|
|
26
|
+
import {
|
|
27
|
+
importEd25519PrivateKeyFromSeedBase64url,
|
|
28
|
+
signEd25519SeedSha256,
|
|
29
|
+
} from "./auth/keys.js";
|
|
30
|
+
import {
|
|
31
|
+
base64urlDecode,
|
|
32
|
+
base64urlEncode,
|
|
33
|
+
toArrayBuffer,
|
|
34
|
+
} from "./auth/utils.js";
|
|
35
|
+
import {
|
|
36
|
+
correctedIatSeconds,
|
|
37
|
+
estimateMidpointClockOffsetMs,
|
|
38
|
+
} from "./auth/time.js";
|
|
39
|
+
import { buildNatsConnectSignaturePayload } from "./auth/session_auth.js";
|
|
40
|
+
import type { TrellisAPI } from "./contracts.js";
|
|
41
|
+
import {
|
|
42
|
+
DEFAULT_RUNTIME_MAX_RECONNECT_ATTEMPTS,
|
|
43
|
+
loadDefaultRuntimeTransport,
|
|
44
|
+
selectRuntimeTransportServers,
|
|
45
|
+
} from "./runtime_transport.js";
|
|
46
|
+
import { ServiceHealth } from "./health.js";
|
|
47
|
+
import { type RuntimeStateStoresForContract, Trellis } from "./trellis.js";
|
|
48
|
+
import { logger as noopLogger, type LoggerLike } from "./globals.js";
|
|
49
|
+
import { TransferError, TransportError } from "./errors/index.js";
|
|
50
|
+
import type {
|
|
51
|
+
ReceiveTransferGrant,
|
|
52
|
+
ReceiveTransferHandle,
|
|
53
|
+
SendTransferGrant,
|
|
54
|
+
SendTransferHandle,
|
|
55
|
+
} from "./transfer.js";
|
|
56
|
+
import { type StaticDecode, Type } from "typebox";
|
|
57
|
+
import { Value } from "typebox/value";
|
|
58
|
+
import {
|
|
59
|
+
observeNatsTrellisConnection,
|
|
60
|
+
type TrellisConnection,
|
|
61
|
+
} from "./connection.js";
|
|
62
|
+
|
|
63
|
+
type DeviceContract<
|
|
64
|
+
TApi extends TrellisAPI = TrellisAPI,
|
|
65
|
+
TContract extends {
|
|
66
|
+
state?: Readonly<Record<string, unknown>>;
|
|
67
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
68
|
+
} = {
|
|
69
|
+
state?: Readonly<Record<string, unknown>>;
|
|
70
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
71
|
+
},
|
|
72
|
+
> = {
|
|
73
|
+
CONTRACT_ID: string;
|
|
74
|
+
CONTRACT_DIGEST: string;
|
|
75
|
+
CONTRACT: TContract & {
|
|
76
|
+
displayName?: string;
|
|
77
|
+
};
|
|
78
|
+
API: {
|
|
79
|
+
trellis: TApi;
|
|
80
|
+
};
|
|
81
|
+
readonly [CONTRACT_STATE_METADATA]?: ContractStateMetadata;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
type DeviceContractApi<TContract extends DeviceContract> =
|
|
85
|
+
TContract["API"]["trellis"];
|
|
86
|
+
|
|
87
|
+
type DeviceRuntime<
|
|
88
|
+
TApi extends TrellisAPI,
|
|
89
|
+
TState extends Record<string, { kind: "value" | "map"; value: unknown }>,
|
|
90
|
+
> = Trellis<TApi, "client", TState>;
|
|
91
|
+
|
|
92
|
+
type RuntimeStateShape = Record<
|
|
93
|
+
string,
|
|
94
|
+
{ kind: "value" | "map"; value: unknown }
|
|
95
|
+
>;
|
|
96
|
+
type BroadStateStore = {
|
|
97
|
+
get(...args: unknown[]): AsyncResult<unknown, BaseError>;
|
|
98
|
+
put(...args: unknown[]): AsyncResult<unknown, BaseError>;
|
|
99
|
+
list(...args: unknown[]): AsyncResult<unknown, BaseError>;
|
|
100
|
+
delete(...args: unknown[]): AsyncResult<unknown, BaseError>;
|
|
101
|
+
};
|
|
102
|
+
type BroadStateFacade = Record<string, BroadStateStore>;
|
|
103
|
+
|
|
104
|
+
function deviceConnectResult<T>(
|
|
105
|
+
promise: Promise<T>,
|
|
106
|
+
): AsyncResult<T, TransportError | UnexpectedError> {
|
|
107
|
+
return AsyncResult.from(
|
|
108
|
+
promise.then(
|
|
109
|
+
(
|
|
110
|
+
value,
|
|
111
|
+
): Result<T, TransportError | UnexpectedError> => Result.ok(value),
|
|
112
|
+
(
|
|
113
|
+
cause,
|
|
114
|
+
): Result<T, TransportError | UnexpectedError> =>
|
|
115
|
+
Result.err(
|
|
116
|
+
cause instanceof TransportError
|
|
117
|
+
? cause
|
|
118
|
+
: new UnexpectedError({ cause }),
|
|
119
|
+
),
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type TrellisDeviceConnection<
|
|
125
|
+
TApi extends TrellisAPI = TrellisAPI,
|
|
126
|
+
TState extends Record<string, { kind: "value" | "map"; value: unknown }> = {},
|
|
127
|
+
> = {
|
|
128
|
+
readonly request: DeviceRuntime<TApi, TState>["request"];
|
|
129
|
+
readonly publish: DeviceRuntime<TApi, TState>["publish"];
|
|
130
|
+
readonly event: DeviceRuntime<TApi, TState>["event"];
|
|
131
|
+
readonly operation: DeviceRuntime<TApi, TState>["operation"];
|
|
132
|
+
readonly transfer: {
|
|
133
|
+
(grant: SendTransferGrant): SendTransferHandle;
|
|
134
|
+
(grant: ReceiveTransferGrant): ReceiveTransferHandle;
|
|
135
|
+
};
|
|
136
|
+
readonly state: DeviceRuntime<TApi, TState>["state"];
|
|
137
|
+
readonly name: string;
|
|
138
|
+
readonly timeout: number;
|
|
139
|
+
readonly stream: string;
|
|
140
|
+
readonly api: TApi;
|
|
141
|
+
readonly connection: TrellisConnection;
|
|
142
|
+
readonly natsConnection: NatsConnection;
|
|
143
|
+
readonly health: ServiceHealth;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
type DeviceConnectTransport = {
|
|
147
|
+
connect(options: {
|
|
148
|
+
servers: string | string[];
|
|
149
|
+
token?: string;
|
|
150
|
+
authenticator?: unknown;
|
|
151
|
+
inboxPrefix?: string;
|
|
152
|
+
maxReconnectAttempts?: number;
|
|
153
|
+
}): Promise<NatsConnection>;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
type DeviceConnectDeps = {
|
|
157
|
+
loadTransport(): Promise<DeviceConnectTransport>;
|
|
158
|
+
now(): number;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const ClientTransportEndpointsSchema = Type.Object({
|
|
162
|
+
natsServers: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const ClientTransportsSchema = Type.Object({
|
|
166
|
+
native: Type.Optional(ClientTransportEndpointsSchema),
|
|
167
|
+
websocket: Type.Optional(ClientTransportEndpointsSchema),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
export type TrellisDevicePendingActivationState = {
|
|
171
|
+
status: "pending";
|
|
172
|
+
contractDigest: string;
|
|
173
|
+
publicIdentityKey: string;
|
|
174
|
+
instanceId: string;
|
|
175
|
+
deploymentId: string;
|
|
176
|
+
flowId: string;
|
|
177
|
+
nonce: string;
|
|
178
|
+
activationUrl: string;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export type TrellisDeviceActivatedActivationState = {
|
|
182
|
+
status: "activated";
|
|
183
|
+
contractDigest: string;
|
|
184
|
+
publicIdentityKey: string;
|
|
185
|
+
instanceId: string;
|
|
186
|
+
deploymentId: string;
|
|
187
|
+
flowId: string;
|
|
188
|
+
nonce: string;
|
|
189
|
+
activationUrl: string;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export type TrellisDeviceLocalActivationState =
|
|
193
|
+
| TrellisDevicePendingActivationState
|
|
194
|
+
| TrellisDeviceActivatedActivationState;
|
|
195
|
+
|
|
196
|
+
export type TrellisDeviceActivationSession<
|
|
197
|
+
TState extends TrellisDeviceLocalActivationState =
|
|
198
|
+
TrellisDeviceLocalActivationState,
|
|
199
|
+
> = {
|
|
200
|
+
activationUrl: string;
|
|
201
|
+
localState: TState;
|
|
202
|
+
waitForOnlineApproval(opts?: {
|
|
203
|
+
signal?: AbortSignal;
|
|
204
|
+
}): Promise<TrellisDeviceActivatedActivationState>;
|
|
205
|
+
acceptConfirmationCode(
|
|
206
|
+
code: string,
|
|
207
|
+
): Promise<TrellisDeviceActivatedActivationState>;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export type TrellisDeviceActivationArgs<
|
|
211
|
+
TApi extends TrellisAPI = TrellisAPI,
|
|
212
|
+
TContract extends DeviceContract<TApi, {
|
|
213
|
+
state?: Readonly<Record<string, unknown>>;
|
|
214
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
215
|
+
}> = DeviceContract<TApi, {
|
|
216
|
+
state?: Readonly<Record<string, unknown>>;
|
|
217
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
218
|
+
}>,
|
|
219
|
+
> = {
|
|
220
|
+
trellisUrl: string;
|
|
221
|
+
contract: TContract;
|
|
222
|
+
rootSecret: Uint8Array | string;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export type TrellisDeviceResumeActivationArgs<
|
|
226
|
+
TApi extends TrellisAPI = TrellisAPI,
|
|
227
|
+
TContract extends DeviceContract<TApi, {
|
|
228
|
+
state?: Readonly<Record<string, unknown>>;
|
|
229
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
230
|
+
}> = DeviceContract<TApi, {
|
|
231
|
+
state?: Readonly<Record<string, unknown>>;
|
|
232
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
233
|
+
}>,
|
|
234
|
+
> = TrellisDeviceActivationArgs<TApi, TContract> & {
|
|
235
|
+
localState: TrellisDeviceLocalActivationState;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export type TrellisDeviceConnectArgs<
|
|
239
|
+
TApi extends TrellisAPI = TrellisAPI,
|
|
240
|
+
TContract extends DeviceContract<TApi, {
|
|
241
|
+
state?: Readonly<Record<string, unknown>>;
|
|
242
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
243
|
+
}> = DeviceContract<TApi, {
|
|
244
|
+
state?: Readonly<Record<string, unknown>>;
|
|
245
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
246
|
+
}>,
|
|
247
|
+
> = {
|
|
248
|
+
trellisUrl: string;
|
|
249
|
+
contract: TContract;
|
|
250
|
+
rootSecret: Uint8Array | string;
|
|
251
|
+
log?: LoggerLike | false;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const DeviceBootstrapReadySchema = Type.Object({
|
|
255
|
+
status: Type.Literal("ready"),
|
|
256
|
+
connectInfo: Type.Object({
|
|
257
|
+
instanceId: Type.String({ minLength: 1 }),
|
|
258
|
+
deploymentId: Type.String({ minLength: 1 }),
|
|
259
|
+
contractId: Type.String({ minLength: 1 }),
|
|
260
|
+
contractDigest: Type.String({ minLength: 1 }),
|
|
261
|
+
transports: ClientTransportsSchema,
|
|
262
|
+
transport: Type.Object({
|
|
263
|
+
sentinel: Type.Object({
|
|
264
|
+
jwt: Type.String({ minLength: 1 }),
|
|
265
|
+
seed: Type.String({ minLength: 1 }),
|
|
266
|
+
}),
|
|
267
|
+
}),
|
|
268
|
+
auth: Type.Object({
|
|
269
|
+
mode: Type.Literal("device_identity"),
|
|
270
|
+
iatSkewSeconds: Type.Integer({ minimum: 1 }),
|
|
271
|
+
}),
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
const DeviceBootstrapActivationRequiredSchema = Type.Object({
|
|
276
|
+
status: Type.Literal("activation_required"),
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const DeviceBootstrapNotReadySchema = Type.Object({
|
|
280
|
+
status: Type.Literal("not_ready"),
|
|
281
|
+
reason: Type.String({ minLength: 1 }),
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
type DeviceBootstrapReady = StaticDecode<typeof DeviceBootstrapReadySchema>;
|
|
285
|
+
type DeviceBootstrapActivationRequired = StaticDecode<
|
|
286
|
+
typeof DeviceBootstrapActivationRequiredSchema
|
|
287
|
+
>;
|
|
288
|
+
type DeviceBootstrapNotReady = StaticDecode<
|
|
289
|
+
typeof DeviceBootstrapNotReadySchema
|
|
290
|
+
>;
|
|
291
|
+
type DeviceBootstrapResponse =
|
|
292
|
+
| DeviceBootstrapReady
|
|
293
|
+
| DeviceBootstrapActivationRequired
|
|
294
|
+
| DeviceBootstrapNotReady;
|
|
295
|
+
type ResolvedDeviceConnectInfo = DeviceBootstrapReady["connectInfo"];
|
|
296
|
+
type DeviceClockOffsetState = {
|
|
297
|
+
serverClockOffsetMs: number;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
function normalizeRootSecret(rootSecret: Uint8Array | string): Uint8Array {
|
|
301
|
+
if (typeof rootSecret === "string") {
|
|
302
|
+
const decoded = base64urlDecode(rootSecret.trim());
|
|
303
|
+
if (decoded.length === 0) throw new Error("rootSecret must not be empty");
|
|
304
|
+
return decoded;
|
|
305
|
+
}
|
|
306
|
+
if (rootSecret.length === 0) throw new Error("rootSecret must not be empty");
|
|
307
|
+
return rootSecret;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function signIdentityBytes(
|
|
311
|
+
identitySeed: Uint8Array,
|
|
312
|
+
data: Uint8Array,
|
|
313
|
+
): Promise<Uint8Array> {
|
|
314
|
+
const privateKey = await importEd25519PrivateKeyFromSeedBase64url(
|
|
315
|
+
base64urlEncode(identitySeed),
|
|
316
|
+
);
|
|
317
|
+
return new Uint8Array(
|
|
318
|
+
await crypto.subtle.sign("Ed25519", privateKey, toArrayBuffer(data)),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function createDeviceNatsAuthTokenAuthenticator(args: {
|
|
323
|
+
publicIdentityKey: string;
|
|
324
|
+
identitySeed: Uint8Array;
|
|
325
|
+
contractDigest: string;
|
|
326
|
+
now: () => number;
|
|
327
|
+
getServerClockOffsetMs: () => number;
|
|
328
|
+
}): Authenticator {
|
|
329
|
+
return () => {
|
|
330
|
+
const iat = correctedIatSeconds(
|
|
331
|
+
args.now(),
|
|
332
|
+
args.getServerClockOffsetMs(),
|
|
333
|
+
);
|
|
334
|
+
const sig = signEd25519SeedSha256(
|
|
335
|
+
args.identitySeed,
|
|
336
|
+
new TextEncoder().encode(
|
|
337
|
+
`nats-connect:${
|
|
338
|
+
buildNatsConnectSignaturePayload(iat, args.contractDigest)
|
|
339
|
+
}`,
|
|
340
|
+
),
|
|
341
|
+
);
|
|
342
|
+
return {
|
|
343
|
+
auth_token: JSON.stringify({
|
|
344
|
+
v: 1,
|
|
345
|
+
sessionKey: args.publicIdentityKey,
|
|
346
|
+
iat,
|
|
347
|
+
sig: base64urlEncode(new Uint8Array(sig)),
|
|
348
|
+
contractDigest: args.contractDigest,
|
|
349
|
+
}),
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const defaultDeps: DeviceConnectDeps = {
|
|
355
|
+
loadTransport: loadDefaultRuntimeTransport,
|
|
356
|
+
now: () => Date.now(),
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
function transportCauseContext(cause: unknown): Record<string, unknown> {
|
|
360
|
+
if (cause instanceof Error) {
|
|
361
|
+
return { causeName: cause.name, causeMessage: cause.message };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return { cause: String(cause) };
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function createTransportError(args: {
|
|
368
|
+
code: string;
|
|
369
|
+
message: string;
|
|
370
|
+
hint: string;
|
|
371
|
+
context?: Record<string, unknown>;
|
|
372
|
+
cause?: unknown;
|
|
373
|
+
}): TransportError {
|
|
374
|
+
return new TransportError({
|
|
375
|
+
code: args.code,
|
|
376
|
+
message: args.message,
|
|
377
|
+
hint: args.hint,
|
|
378
|
+
cause: args.cause,
|
|
379
|
+
context: {
|
|
380
|
+
...(args.context ?? {}),
|
|
381
|
+
...(args.cause === undefined ? {} : transportCauseContext(args.cause)),
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function assertBootstrapContractMatches(args: {
|
|
387
|
+
contractId: string;
|
|
388
|
+
contractDigest: string;
|
|
389
|
+
connectInfo: ResolvedDeviceConnectInfo;
|
|
390
|
+
}): void {
|
|
391
|
+
if (
|
|
392
|
+
args.connectInfo.contractId !== args.contractId ||
|
|
393
|
+
args.connectInfo.contractDigest !== args.contractDigest
|
|
394
|
+
) {
|
|
395
|
+
throw createTransportError({
|
|
396
|
+
code: "trellis.bootstrap.contract_mismatch",
|
|
397
|
+
message:
|
|
398
|
+
"Trellis returned connection details for a different device contract.",
|
|
399
|
+
hint:
|
|
400
|
+
"Retry the connection. If it keeps happening, check the requested device contract and Trellis activation state.",
|
|
401
|
+
context: {
|
|
402
|
+
requestedContractId: args.contractId,
|
|
403
|
+
requestedContractDigest: args.contractDigest,
|
|
404
|
+
returnedContractId: args.connectInfo.contractId,
|
|
405
|
+
returnedContractDigest: args.connectInfo.contractDigest,
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async function readJsonResponse(
|
|
412
|
+
response: Response,
|
|
413
|
+
args: {
|
|
414
|
+
code: string;
|
|
415
|
+
message: string;
|
|
416
|
+
hint: string;
|
|
417
|
+
context?: Record<string, unknown>;
|
|
418
|
+
},
|
|
419
|
+
): Promise<unknown> {
|
|
420
|
+
try {
|
|
421
|
+
return await response.json();
|
|
422
|
+
} catch (cause) {
|
|
423
|
+
throw createTransportError({
|
|
424
|
+
...args,
|
|
425
|
+
cause,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function parseResponseRecord(text: string): Record<string, unknown> | null {
|
|
431
|
+
if (text.length === 0) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
try {
|
|
435
|
+
const parsed = JSON.parse(text);
|
|
436
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
437
|
+
? parsed as Record<string, unknown>
|
|
438
|
+
: null;
|
|
439
|
+
} catch {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function resolveDeviceLogger(log?: LoggerLike | false): LoggerLike {
|
|
445
|
+
if (log === false) {
|
|
446
|
+
return noopLogger;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return log ?? noopLogger;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
async function readResponseReason(response: Response): Promise<string | null> {
|
|
453
|
+
const text = await response.text();
|
|
454
|
+
if (!text) {
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
try {
|
|
459
|
+
const parsed = JSON.parse(text) as Record<string, unknown>;
|
|
460
|
+
if (typeof parsed.reason === "string" && parsed.reason.length > 0) {
|
|
461
|
+
return parsed.reason;
|
|
462
|
+
}
|
|
463
|
+
} catch {
|
|
464
|
+
return text;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return text;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
function createActivationRequiredTransportError(
|
|
471
|
+
context?: Record<string, unknown>,
|
|
472
|
+
) {
|
|
473
|
+
return createTransportError({
|
|
474
|
+
code: "trellis.bootstrap.activation_required",
|
|
475
|
+
message: "Trellis requires device activation before connecting.",
|
|
476
|
+
hint:
|
|
477
|
+
"Start or resume device activation, then retry the runtime connection after activation completes.",
|
|
478
|
+
context,
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function createInvalidConfirmationCodeTransportError(
|
|
483
|
+
context?: Record<string, unknown>,
|
|
484
|
+
) {
|
|
485
|
+
return createTransportError({
|
|
486
|
+
code: "trellis.device.invalid_confirmation_code",
|
|
487
|
+
message: "The device confirmation code is invalid.",
|
|
488
|
+
hint:
|
|
489
|
+
"Retry with the current confirmation code for this activation, or restart activation if the code is no longer valid.",
|
|
490
|
+
context,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function createActivatedLocalState(
|
|
495
|
+
localState: TrellisDeviceLocalActivationState,
|
|
496
|
+
): TrellisDeviceActivatedActivationState {
|
|
497
|
+
return {
|
|
498
|
+
...localState,
|
|
499
|
+
status: "activated",
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function assertActivationStateMatchesIdentity(args: {
|
|
504
|
+
localState: TrellisDeviceLocalActivationState;
|
|
505
|
+
publicIdentityKey: string;
|
|
506
|
+
}): void {
|
|
507
|
+
if (args.localState.publicIdentityKey !== args.publicIdentityKey) {
|
|
508
|
+
throw createTransportError({
|
|
509
|
+
code: "trellis.device.activation_state_mismatch",
|
|
510
|
+
message:
|
|
511
|
+
"Local device activation state does not match the provided root secret.",
|
|
512
|
+
hint:
|
|
513
|
+
"Use the activation state for the same device identity, or start a new activation for this root secret.",
|
|
514
|
+
context: {
|
|
515
|
+
statePublicIdentityKey: args.localState.publicIdentityKey,
|
|
516
|
+
publicIdentityKey: args.publicIdentityKey,
|
|
517
|
+
},
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function assertActivationStateMatchesContract(args: {
|
|
523
|
+
localState: TrellisDeviceLocalActivationState;
|
|
524
|
+
contractDigest: string;
|
|
525
|
+
}): void {
|
|
526
|
+
if (args.localState.contractDigest !== args.contractDigest) {
|
|
527
|
+
throw createTransportError({
|
|
528
|
+
code: "trellis.device.activation_state_contract_mismatch",
|
|
529
|
+
message:
|
|
530
|
+
"Local device activation state does not match the requested device contract.",
|
|
531
|
+
hint:
|
|
532
|
+
"Use activation state for the same device contract, or start activation again for this contract digest.",
|
|
533
|
+
context: {
|
|
534
|
+
stateContractDigest: args.localState.contractDigest,
|
|
535
|
+
contractDigest: args.contractDigest,
|
|
536
|
+
},
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async function createActivationSession<
|
|
542
|
+
TLocalState extends TrellisDeviceLocalActivationState,
|
|
543
|
+
>(args: {
|
|
544
|
+
trellisUrl: string;
|
|
545
|
+
contractDigest: string;
|
|
546
|
+
identity: Awaited<ReturnType<typeof deriveDeviceIdentity>>;
|
|
547
|
+
localState: TLocalState;
|
|
548
|
+
}): Promise<TrellisDeviceActivationSession<TLocalState>> {
|
|
549
|
+
assertActivationStateMatchesIdentity({
|
|
550
|
+
localState: args.localState,
|
|
551
|
+
publicIdentityKey: args.identity.publicIdentityKey,
|
|
552
|
+
});
|
|
553
|
+
assertActivationStateMatchesContract({
|
|
554
|
+
localState: args.localState,
|
|
555
|
+
contractDigest: args.contractDigest,
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
const activatedState = createActivatedLocalState(args.localState);
|
|
559
|
+
return {
|
|
560
|
+
activationUrl: args.localState.activationUrl,
|
|
561
|
+
localState: args.localState,
|
|
562
|
+
waitForOnlineApproval: async (opts?: { signal?: AbortSignal }) => {
|
|
563
|
+
if (args.localState.status === "activated") {
|
|
564
|
+
return activatedState;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
await waitForDeviceActivation({
|
|
568
|
+
trellisUrl: args.trellisUrl,
|
|
569
|
+
flowId: args.localState.flowId,
|
|
570
|
+
publicIdentityKey: args.identity.publicIdentityKey,
|
|
571
|
+
nonce: args.localState.nonce,
|
|
572
|
+
identitySeed: args.identity.identitySeed,
|
|
573
|
+
contractDigest: args.contractDigest,
|
|
574
|
+
signal: opts?.signal,
|
|
575
|
+
});
|
|
576
|
+
return activatedState;
|
|
577
|
+
},
|
|
578
|
+
acceptConfirmationCode: async (code: string) => {
|
|
579
|
+
if (args.localState.status === "activated") {
|
|
580
|
+
return activatedState;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const ok = await verifyDeviceConfirmationCode({
|
|
584
|
+
activationKey: args.identity.activationKey,
|
|
585
|
+
publicIdentityKey: args.identity.publicIdentityKey,
|
|
586
|
+
nonce: args.localState.nonce,
|
|
587
|
+
confirmationCode: code,
|
|
588
|
+
});
|
|
589
|
+
if (!ok) {
|
|
590
|
+
throw createInvalidConfirmationCodeTransportError({
|
|
591
|
+
publicIdentityKey: args.identity.publicIdentityKey,
|
|
592
|
+
instanceId: args.localState.instanceId,
|
|
593
|
+
deploymentId: args.localState.deploymentId,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
return activatedState;
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async function fetchDeviceBootstrap(args: {
|
|
602
|
+
trellisUrl: string;
|
|
603
|
+
publicIdentityKey: string;
|
|
604
|
+
identitySeed: Uint8Array | string;
|
|
605
|
+
contractDigest: string;
|
|
606
|
+
now: () => number;
|
|
607
|
+
offsetState: DeviceClockOffsetState;
|
|
608
|
+
}): Promise<DeviceBootstrapResponse> {
|
|
609
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
610
|
+
const requestStartedAtMs = args.now();
|
|
611
|
+
const request = await signDeviceWaitRequest({
|
|
612
|
+
flowId: "connect-info",
|
|
613
|
+
publicIdentityKey: args.publicIdentityKey,
|
|
614
|
+
nonce: "connect-info",
|
|
615
|
+
identitySeed: args.identitySeed,
|
|
616
|
+
contractDigest: args.contractDigest,
|
|
617
|
+
iat: correctedIatSeconds(
|
|
618
|
+
requestStartedAtMs,
|
|
619
|
+
args.offsetState.serverClockOffsetMs,
|
|
620
|
+
),
|
|
621
|
+
});
|
|
622
|
+
const bootstrapRequest = {
|
|
623
|
+
publicIdentityKey: request.publicIdentityKey,
|
|
624
|
+
contractDigest: request.contractDigest,
|
|
625
|
+
iat: request.iat,
|
|
626
|
+
sig: request.sig,
|
|
627
|
+
};
|
|
628
|
+
const response = await fetch(
|
|
629
|
+
new URL("/auth/devices/connect-info", args.trellisUrl),
|
|
630
|
+
{
|
|
631
|
+
method: "POST",
|
|
632
|
+
headers: { "Content-Type": "application/json" },
|
|
633
|
+
body: JSON.stringify(bootstrapRequest),
|
|
634
|
+
},
|
|
635
|
+
);
|
|
636
|
+
const responseReceivedAtMs = args.now();
|
|
637
|
+
if (!response.ok) {
|
|
638
|
+
const responseText = await response.text();
|
|
639
|
+
const parsed = parseResponseRecord(responseText);
|
|
640
|
+
const reason = typeof parsed?.reason === "string"
|
|
641
|
+
? parsed.reason
|
|
642
|
+
: responseText;
|
|
643
|
+
const serverNow = typeof parsed?.serverNow === "number"
|
|
644
|
+
? parsed.serverNow
|
|
645
|
+
: null;
|
|
646
|
+
if (
|
|
647
|
+
attempt === 0 &&
|
|
648
|
+
response.status === 400 &&
|
|
649
|
+
reason === "iat_out_of_range" &&
|
|
650
|
+
serverNow !== null
|
|
651
|
+
) {
|
|
652
|
+
args.offsetState.serverClockOffsetMs = estimateMidpointClockOffsetMs({
|
|
653
|
+
requestStartedAtMs,
|
|
654
|
+
responseReceivedAtMs,
|
|
655
|
+
serverNowSeconds: serverNow,
|
|
656
|
+
});
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
if (
|
|
660
|
+
response.status === 404 &&
|
|
661
|
+
(reason === "unknown_device" || reason === "activation_required")
|
|
662
|
+
) {
|
|
663
|
+
return { status: "activation_required" };
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
throw createTransportError({
|
|
667
|
+
code: "trellis.bootstrap.failed",
|
|
668
|
+
message: "Trellis could not prepare the device session.",
|
|
669
|
+
hint:
|
|
670
|
+
"Retry the connection. If it keeps failing, check Trellis availability and device activation state.",
|
|
671
|
+
context: {
|
|
672
|
+
trellisUrl: args.trellisUrl,
|
|
673
|
+
status: response.status,
|
|
674
|
+
reason,
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const payload = await readJsonResponse(response, {
|
|
680
|
+
code: "trellis.bootstrap.invalid_response",
|
|
681
|
+
message: "Trellis returned an invalid bootstrap response.",
|
|
682
|
+
hint:
|
|
683
|
+
"Retry the connection. If it keeps happening, check the Trellis deployment.",
|
|
684
|
+
context: { trellisUrl: args.trellisUrl },
|
|
685
|
+
});
|
|
686
|
+
if (
|
|
687
|
+
payload && typeof payload === "object" &&
|
|
688
|
+
typeof (payload as { serverNow?: unknown }).serverNow === "number"
|
|
689
|
+
) {
|
|
690
|
+
args.offsetState.serverClockOffsetMs = estimateMidpointClockOffsetMs({
|
|
691
|
+
requestStartedAtMs,
|
|
692
|
+
responseReceivedAtMs,
|
|
693
|
+
serverNowSeconds: (payload as { serverNow: number }).serverNow,
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
if (Value.Check(DeviceBootstrapReadySchema, payload)) return payload;
|
|
697
|
+
if (Value.Check(DeviceBootstrapActivationRequiredSchema, payload)) {
|
|
698
|
+
return payload;
|
|
699
|
+
}
|
|
700
|
+
if (Value.Check(DeviceBootstrapNotReadySchema, payload)) return payload;
|
|
701
|
+
throw createTransportError({
|
|
702
|
+
code: "trellis.bootstrap.invalid_response",
|
|
703
|
+
message: "Trellis returned an invalid bootstrap response.",
|
|
704
|
+
hint:
|
|
705
|
+
"Retry the connection. If it keeps happening, check the Trellis deployment.",
|
|
706
|
+
context: { trellisUrl: args.trellisUrl },
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
throw createTransportError({
|
|
711
|
+
code: "trellis.bootstrap.time_sync_failed",
|
|
712
|
+
message: "Trellis could not confirm the device time window.",
|
|
713
|
+
hint:
|
|
714
|
+
"Retry the connection. If it keeps happening, check the device and Trellis clocks.",
|
|
715
|
+
context: { trellisUrl: args.trellisUrl },
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
export async function startDeviceActivationWithDeps<
|
|
720
|
+
TContract extends DeviceContract<TrellisAPI, {
|
|
721
|
+
state?: Readonly<Record<string, unknown>>;
|
|
722
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
723
|
+
}>,
|
|
724
|
+
>(
|
|
725
|
+
args: TrellisDeviceActivationArgs<DeviceContractApi<TContract>, TContract>,
|
|
726
|
+
_deps: Pick<DeviceConnectDeps, "now">,
|
|
727
|
+
): Promise<
|
|
728
|
+
TrellisDeviceActivationSession<TrellisDevicePendingActivationState>
|
|
729
|
+
> {
|
|
730
|
+
const rootSecret = normalizeRootSecret(args.rootSecret);
|
|
731
|
+
const identity = await deriveDeviceIdentity(rootSecret);
|
|
732
|
+
const nonce = crypto.randomUUID();
|
|
733
|
+
const payload = await buildDeviceActivationPayload({
|
|
734
|
+
activationKey: identity.activationKey,
|
|
735
|
+
publicIdentityKey: identity.publicIdentityKey,
|
|
736
|
+
nonce,
|
|
737
|
+
});
|
|
738
|
+
const activation = await startDeviceActivationRequest({
|
|
739
|
+
trellisUrl: args.trellisUrl,
|
|
740
|
+
payload,
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
return await createActivationSession({
|
|
744
|
+
trellisUrl: args.trellisUrl,
|
|
745
|
+
contractDigest: args.contract.CONTRACT_DIGEST,
|
|
746
|
+
identity,
|
|
747
|
+
localState: {
|
|
748
|
+
status: "pending",
|
|
749
|
+
contractDigest: args.contract.CONTRACT_DIGEST,
|
|
750
|
+
publicIdentityKey: identity.publicIdentityKey,
|
|
751
|
+
instanceId: activation.instanceId,
|
|
752
|
+
deploymentId: activation.deploymentId,
|
|
753
|
+
flowId: activation.flowId,
|
|
754
|
+
nonce,
|
|
755
|
+
activationUrl: activation.activationUrl,
|
|
756
|
+
},
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
export async function resumeDeviceActivationWithDeps<
|
|
761
|
+
TLocalState extends TrellisDeviceLocalActivationState,
|
|
762
|
+
TContract extends DeviceContract<TrellisAPI, {
|
|
763
|
+
state?: Readonly<Record<string, unknown>>;
|
|
764
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
765
|
+
}>,
|
|
766
|
+
>(
|
|
767
|
+
args:
|
|
768
|
+
& TrellisDeviceResumeActivationArgs<DeviceContractApi<TContract>, TContract>
|
|
769
|
+
& {
|
|
770
|
+
localState: TLocalState;
|
|
771
|
+
},
|
|
772
|
+
_deps: Pick<DeviceConnectDeps, "now">,
|
|
773
|
+
): Promise<TrellisDeviceActivationSession<TLocalState>> {
|
|
774
|
+
const rootSecret = normalizeRootSecret(args.rootSecret);
|
|
775
|
+
const identity = await deriveDeviceIdentity(rootSecret);
|
|
776
|
+
|
|
777
|
+
return await createActivationSession({
|
|
778
|
+
trellisUrl: args.trellisUrl,
|
|
779
|
+
contractDigest: args.contract.CONTRACT_DIGEST,
|
|
780
|
+
identity,
|
|
781
|
+
localState: args.localState,
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
export async function connectDeviceWithDeps<
|
|
786
|
+
TContract extends DeviceContract<TrellisAPI, {
|
|
787
|
+
state?: Readonly<Record<string, unknown>>;
|
|
788
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
789
|
+
}>,
|
|
790
|
+
>(
|
|
791
|
+
args: TrellisDeviceConnectArgs<DeviceContractApi<TContract>, TContract>,
|
|
792
|
+
deps: DeviceConnectDeps,
|
|
793
|
+
): Promise<
|
|
794
|
+
TrellisDeviceConnection<
|
|
795
|
+
DeviceContractApi<TContract>,
|
|
796
|
+
RuntimeStateStoresForContract<TContract>
|
|
797
|
+
>
|
|
798
|
+
> {
|
|
799
|
+
const log = resolveDeviceLogger(args.log);
|
|
800
|
+
const rootSecret = normalizeRootSecret(args.rootSecret);
|
|
801
|
+
const identity = await deriveDeviceIdentity(rootSecret);
|
|
802
|
+
const contractDigest = args.contract.CONTRACT_DIGEST;
|
|
803
|
+
const offsetState: DeviceClockOffsetState = { serverClockOffsetMs: 0 };
|
|
804
|
+
const bootstrap = await fetchDeviceBootstrap({
|
|
805
|
+
trellisUrl: args.trellisUrl,
|
|
806
|
+
publicIdentityKey: identity.publicIdentityKey,
|
|
807
|
+
identitySeed: identity.identitySeed,
|
|
808
|
+
contractDigest,
|
|
809
|
+
now: deps.now,
|
|
810
|
+
offsetState,
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
if (bootstrap.status === "activation_required") {
|
|
814
|
+
throw createActivationRequiredTransportError({
|
|
815
|
+
publicIdentityKey: identity.publicIdentityKey,
|
|
816
|
+
contractId: args.contract.CONTRACT_ID,
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (bootstrap.status === "not_ready") {
|
|
821
|
+
throw createTransportError({
|
|
822
|
+
code: "trellis.bootstrap.not_ready",
|
|
823
|
+
message: "Trellis is not ready to connect this device.",
|
|
824
|
+
hint:
|
|
825
|
+
"Wait for the device to be activated and the requested deployment to become available, then try again.",
|
|
826
|
+
context: { reason: bootstrap.reason },
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
const connectInfo = bootstrap.connectInfo;
|
|
831
|
+
assertBootstrapContractMatches({
|
|
832
|
+
contractId: args.contract.CONTRACT_ID,
|
|
833
|
+
contractDigest,
|
|
834
|
+
connectInfo,
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
const transport = await deps.loadTransport();
|
|
838
|
+
let nc: NatsConnection;
|
|
839
|
+
try {
|
|
840
|
+
nc = await transport.connect({
|
|
841
|
+
servers: selectRuntimeTransportServers(connectInfo.transports),
|
|
842
|
+
maxReconnectAttempts: DEFAULT_RUNTIME_MAX_RECONNECT_ATTEMPTS,
|
|
843
|
+
inboxPrefix: `_INBOX.${identity.publicIdentityKey.slice(0, 16)}`,
|
|
844
|
+
authenticator: [
|
|
845
|
+
createDeviceNatsAuthTokenAuthenticator({
|
|
846
|
+
publicIdentityKey: identity.publicIdentityKey,
|
|
847
|
+
identitySeed: identity.identitySeed,
|
|
848
|
+
contractDigest,
|
|
849
|
+
now: deps.now,
|
|
850
|
+
getServerClockOffsetMs: () => offsetState.serverClockOffsetMs,
|
|
851
|
+
}),
|
|
852
|
+
jwtAuthenticator(
|
|
853
|
+
connectInfo.transport.sentinel.jwt,
|
|
854
|
+
new TextEncoder().encode(connectInfo.transport.sentinel.seed),
|
|
855
|
+
),
|
|
856
|
+
],
|
|
857
|
+
});
|
|
858
|
+
} catch (cause) {
|
|
859
|
+
throw createTransportError({
|
|
860
|
+
code: "trellis.runtime.connect_failed",
|
|
861
|
+
message: "Trellis could not open the device runtime connection.",
|
|
862
|
+
hint:
|
|
863
|
+
"Retry the connection. If it keeps failing, check Trellis transport availability.",
|
|
864
|
+
cause,
|
|
865
|
+
context: { contractId: args.contract.CONTRACT_ID },
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const connection = observeNatsTrellisConnection({
|
|
870
|
+
kind: "device",
|
|
871
|
+
nc,
|
|
872
|
+
log: false,
|
|
873
|
+
lifecycleLog: {
|
|
874
|
+
log,
|
|
875
|
+
context: { contractId: args.contract.CONTRACT_ID },
|
|
876
|
+
},
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
const trellis = new Trellis<
|
|
880
|
+
DeviceContractApi<TContract>,
|
|
881
|
+
"client",
|
|
882
|
+
RuntimeStateStoresForContract<TContract>
|
|
883
|
+
>(
|
|
884
|
+
args.contract.CONTRACT_ID,
|
|
885
|
+
nc,
|
|
886
|
+
{
|
|
887
|
+
sessionKey: identity.publicIdentityKey,
|
|
888
|
+
sign: (data: Uint8Array) =>
|
|
889
|
+
signIdentityBytes(identity.identitySeed, data),
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
log,
|
|
893
|
+
api: args.contract.API.trellis,
|
|
894
|
+
state: args.contract[CONTRACT_STATE_METADATA],
|
|
895
|
+
connection,
|
|
896
|
+
},
|
|
897
|
+
);
|
|
898
|
+
|
|
899
|
+
const health = new ServiceHealth({
|
|
900
|
+
serviceName: args.contract.CONTRACT?.displayName ??
|
|
901
|
+
args.contract.CONTRACT_ID,
|
|
902
|
+
kind: "device",
|
|
903
|
+
instanceId: connectInfo.instanceId,
|
|
904
|
+
contractId: connectInfo.contractId,
|
|
905
|
+
contractDigest: connectInfo.contractDigest,
|
|
906
|
+
publishIntervalMs: 30_000,
|
|
907
|
+
});
|
|
908
|
+
health.setInfo({
|
|
909
|
+
info: {
|
|
910
|
+
deploymentId: connectInfo.deploymentId,
|
|
911
|
+
},
|
|
912
|
+
});
|
|
913
|
+
health.add("nats", () => ({
|
|
914
|
+
status: nc.isClosed() ? "failed" : "ok",
|
|
915
|
+
...(nc.isClosed() ? { summary: "NATS connection closed" } : {}),
|
|
916
|
+
}));
|
|
917
|
+
|
|
918
|
+
const heartbeatEventEnabled = Boolean(
|
|
919
|
+
(args.contract.API.trellis.events as Record<string, unknown> | undefined)
|
|
920
|
+
?.["Health.Heartbeat"],
|
|
921
|
+
);
|
|
922
|
+
let heartbeatTimer: ReturnType<typeof setInterval> | undefined;
|
|
923
|
+
let publishingHeartbeat = false;
|
|
924
|
+
const stopHeartbeat = () => {
|
|
925
|
+
if (heartbeatTimer !== undefined) {
|
|
926
|
+
clearInterval(heartbeatTimer);
|
|
927
|
+
heartbeatTimer = undefined;
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
const publishHeartbeat = async (): Promise<void> => {
|
|
931
|
+
if (!heartbeatEventEnabled || publishingHeartbeat) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
publishingHeartbeat = true;
|
|
936
|
+
try {
|
|
937
|
+
const heartbeat = await health.heartbeat();
|
|
938
|
+
await trellis.publish(
|
|
939
|
+
"Health.Heartbeat" as never,
|
|
940
|
+
heartbeat as never,
|
|
941
|
+
);
|
|
942
|
+
} finally {
|
|
943
|
+
publishingHeartbeat = false;
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
if (heartbeatEventEnabled) {
|
|
948
|
+
await publishHeartbeat();
|
|
949
|
+
heartbeatTimer = setInterval(() => {
|
|
950
|
+
void publishHeartbeat();
|
|
951
|
+
}, health.publishIntervalMs);
|
|
952
|
+
void nc.closed().finally(stopHeartbeat);
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
return {
|
|
956
|
+
request: trellis.request.bind(trellis),
|
|
957
|
+
publish: trellis.publish.bind(trellis),
|
|
958
|
+
event: trellis.event.bind(trellis),
|
|
959
|
+
operation: trellis.operation.bind(trellis),
|
|
960
|
+
transfer: trellis.transfer.bind(trellis),
|
|
961
|
+
state: trellis.state,
|
|
962
|
+
name: trellis.name,
|
|
963
|
+
timeout: trellis.timeout,
|
|
964
|
+
stream: trellis.stream,
|
|
965
|
+
api: trellis.api,
|
|
966
|
+
connection: trellis.connection,
|
|
967
|
+
natsConnection: trellis.natsConnection,
|
|
968
|
+
health,
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
export const TrellisDevice = {
|
|
973
|
+
connect<
|
|
974
|
+
TContract extends DeviceContract<TrellisAPI, {
|
|
975
|
+
state?: Readonly<Record<string, unknown>>;
|
|
976
|
+
schemas?: Readonly<Record<string, unknown>>;
|
|
977
|
+
}>,
|
|
978
|
+
>(
|
|
979
|
+
args: TrellisDeviceConnectArgs<DeviceContractApi<TContract>, TContract>,
|
|
980
|
+
): AsyncResult<
|
|
981
|
+
TrellisDeviceConnection<
|
|
982
|
+
DeviceContractApi<TContract>,
|
|
983
|
+
RuntimeStateStoresForContract<TContract>
|
|
984
|
+
>,
|
|
985
|
+
TransportError | UnexpectedError
|
|
986
|
+
> {
|
|
987
|
+
return deviceConnectResult(connectDeviceWithDeps(args, defaultDeps));
|
|
988
|
+
},
|
|
989
|
+
};
|