Skip to content

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

@proof-computer/liskov-runtime

Job-side TypeScript runtime SDK for PROOF Applications that run on Acurast and are bootstrapped by Liskov.

This package is the code that a job imports before its Application starts. It is not a Liskov server SDK, deployment tool, control-plane client, wallet library, or executor library. It runs inside the customer job's Acurast runtime and provides the default Liskov boot path:

  • Acurast environment and _STD_ lookup.
  • Acurast runtime identity, signing, and decrypt helpers.
  • Liskov runtime-env fetch and refresh.
  • Managed runtime secrets.
  • Built-in encrypted Liskov logging.
  • Bounded Liskov runtime diagnostics and health events.
  • Runtime readiness/status and test hooks.

Runtime context

SDK v0.3.39 exposes a read-only snapshot from signed bootstrap:

const runtime = await bootstrapSlipwayRuntime();
const applicationUid = runtime.context?.application.uid;
const updatedContext = await runtime.refreshRuntimeContext();

context is undefined when the server omits it. application.uid is the stable key; name and displayName are labels. The WAN IP and IP-derived geography describe this job's observed network; check the geolocation status before treating it as current. Refresh makes one signed request and replaces the snapshot only on success. It starts no polling or backoff and never logs the context. LiskovRuntimeContextRefusedError carries code, status, and retryable (429/503 are retryable; replay 409 is not). A refresh requires a signed bootstrap binding; otherwise it throws SlipwayRuntimeNotReadyError.

Install

The first supported dependency source is the public GitHub release tag:

{
  "dependencies": {
    "@proof-computer/liskov-runtime": "github:proof-computer/liskov-runtime-js#v0.3.39"
  }
}

npmjs publication is a separate release step and is not required for the initial runtime cutover.

The package tarball intentionally contains only dist, LICENSE, README.md, SECURITY.md, and package metadata. Example source and tests stay in the repository.

Runtime v0.3.21 opts Liskov-owned POST requests into the server response tunnel used by Acurast processors that omit successful httpPOST response bodies. The adapter unwraps the original 2xx status and JSON before bootstrap, secrets, or logging callers see it; ordinary fetch transports and servers that do not recognize the opt-in header retain their existing behavior.

The next release runs on Acurast's iOS processor. There httpPOST is deprecated and the global fetch fails, so on process.platform === "ios" the SDK sends its own requests over Node's http/https modules (defaultRuntimeFetch()), and createAcurastRuntimeFetch() gives a job the same choice: Node's modules on iOS, otherwise the httpPOST adapter, else the global fetch. The choice is by platform, so a request is never sent twice. iOS also answers an empty string from environment(name) for an unset name; the SDK treats an empty value as unset, so the job and processor ids come from _STD_.job.getId() and _STD_.device.getAddress().

Runtime v0.3.22 adds identity-bound v2 diagnostics and a terminal application boundary. handle.diagnostics.report(...) sends ordinary signed events, while handle.diagnostics.fatal(...) is first-call-wins, closes health and logging, and makes one bounded signed attempt before the caller terminates. Applications can install installLiskovRuntimeProcessFailureHandlers(...), attach the handle immediately after bootstrap, and choose an explicit "continue" or "exit" policy for unhandled rejections. Bootstrap failures after identity resolution are reported even when bootstrap never returns a handle.

Runtime v0.3.23 treats each process boot within an Acurast registration as a distinct runtime instance. The SDK creates and signs one runtime-bootstrap nonce per process and reuses it across HTTP retries. New backends return that nonce as runtimeInstanceId, which the SDK binds into signed proof.liskov.runtime-diagnostic.v3 events; older responses remain supported through the v2 diagnostic fallback.

Runtime v0.3.24 makes the canonical Application UID authoritative for new first-party runtime sessions while preserving the legacy Application ID in every compatibility surface. Runtime bootstrap v2 carries both identifiers; signed Runtime Environment v2, secret request/response/encrypted-payload v2, logging config v2, and runtime diagnostics v4 bind them where applicable. A UID-bearing request fails closed on a missing UID, binding mismatch, or protocol downgrade; v1-v3 contracts remain available for previously published jobs.

Runtime v0.3.25 makes a successful signed bootstrap authoritative over legacy bootstrap configuration delivered in the initial environment. This preserves the UID from the v2 response for Runtime Environment v2, secrets protocol v2, and runtime diagnostics v4 instead of silently continuing on the legacy identifier-only configuration.

Runtime v0.3.26 propagates that authenticated UID into the optional status().applicationUid field, runtime-start capability attributes, and the base structured log record. Legacy v1 inputs continue to omit the field; the SDK never derives a UID from an Application slug.

Runtime v0.3.27 exposes cooperative cease through the supported bootstrap API. Registering onCease advertises cooperative_cease.v1 on UID-bound V4 diagnostics; older V2/V3 paths do not advertise a command they cannot receive. The SDK validates the identity-bound command, invokes the asynchronous handler at most once per command in each process, and retries the signed outcome on a later check-in if acknowledgement delivery was lost. A new process may handle a still-pending command after restart.

Version 0.3.39 adds opt-in application readiness on signed V4 diagnostics. Enable applicationReadiness: true at bootstrap, then call runtime.applicationReady() once the application can serve. This is separate from SDK readiness (whenReady() / status().ready).

Minimal Entrypoint

Use bootstrapSlipwayRuntime() before importing Application code:

import { bootstrapSlipwayRuntime } from "@proof-computer/liskov-runtime";

const runtime = await bootstrapSlipwayRuntime({
  component: "worker",
  revision: process.env.APP_REVISION
});

try {
  await runtime.log("app.boot");
  await runtime.whenReady();
  await import("./app.js");
} finally {
  await runtime.flush();
  runtime.stop();
}

whenReady() is a fail-fast check, not a long polling loop. It resolves with the current status when every required capability is ready, and throws SlipwayRuntimeNotReadyError with the current status when a required capability is pending, failed, or blocked.

Application readiness

Opt in when the application needs time to load or initialize after SDK bootstrap:

const runtime = await bootstrapSlipwayRuntime({ applicationReadiness: true });
await runtime.whenReady(); // Required SDK capabilities are ready.
await startApplication(); // Resolves once the application can serve.
runtime.applicationReady();

With the option, every signed V4 diagnostic, including runtime.start and runtime.health, carries applicationReadiness: "pending" until applicationReady() is called, then "ready" on every later diagnostic. The method is synchronous, idempotent, never throws, and sends no immediate check-in. It does not change whenReady() or status().ready; those describe the SDK's required capabilities, which can be ready while the application is still pending. Without the option, the method has no effect and the SDK adds no readiness attribute. V1, V2 and V3 diagnostics never add it.

Release and tag the SDK and deploy the server readiness changes before relying on this signal to delay predecessor shutdown.

Runtime Handle

bootstrapSlipwayRuntime() returns:

interface BootstrapSlipwayRuntimeHandle {
  readonly home: string;
  readonly env: {
    get(name: string): string | undefined;
    require(name: string): string;
  };
  status(): SlipwayRuntimeStatus;
  whenReady(): Promise<SlipwayRuntimeStatus>;
  applicationReady(): void;
  log(
    event: string,
    details?: Record<string, unknown>,
    options?: { severity?: "debug" | "info" | "warn" | "error"; labels?: Record<string, string> }
  ): Promise<void>;
  flush(): Promise<{ ok: boolean; state: string; flushed: number; pending: number; dropped: number; message?: string }>;
  refreshNow(): Promise<SlipwayRuntimeEnvLoadResult | undefined>;
  stop(): void;
}

Additional readback fields are present for diagnostics and tests: runtimeEnv, lockbox (the secrets readback, under its compatibility key), and runtimeHealth. They are diagnostic fields, not the product API; application code should normally use env, status, whenReady, applicationReady, log, flush, refreshNow, and stop.

stop() is synchronous and idempotent for the current handle shape. It cancels runtime-env refresh, runtime-health timers, and background secret retries. Call flush() first when a one-shot job needs to give logging a final chance.

Bootstrap Options

The top-level options are intentionally small and testable:

await bootstrapSlipwayRuntime({
  appId: "application-id",
  component: "worker",
  revision: "git-or-artifact-revision",
  home: "/runtime/.slipway",
  secrets: { mode: "required" },
  logging: { mode: "background", earlyBufferMaxRecords: 100 },
  runtimeHealth: { intervalMs: 30_000, initialDelayMs: 30_000 },
  onCease: async (command) => {
    await stopApplicationWork(command.reason);
  },
  diagnostics: (event) => console.error(JSON.stringify(event))
});

Common options:

  • appId, component, revision: metadata added to status, diagnostics, and logging records where available.
  • home: explicit state root. Defaults to LISKOV_HOME, then $HOME/.slipway, then /tmp/slipway.
  • secrets.mode: required, background, or off.
  • secrets.retry: background retry budget. Defaults are initialDelayMs=0, intervalMs=5000, maxElapsedMs=60000, and maxAttempts=12.
  • logging.mode: required, background, or off. The default is background.
  • logging.earlyBufferMaxRecords: in-memory log records to keep before logging config is available. Default: 100.
  • logging.spoolMode: auto, disk, or memory.
  • logging.spoolDir: override the logging spool directory.
  • logging.timeoutMs: network timeout for logging writes.
  • logging.onError: observes logging failures without breaking the runtime wrapper.
  • diagnostics: local callback for redacted runtime diagnostics.
  • diagnosticSendTimeoutMs, diagnosticRemoteBackoffMs: bounds for remote runtime-diagnostic delivery.
  • runtimeHealth: optional interval/initial-delay/send-timeout overrides for runtime.health diagnostics.
  • applicationReadiness: opt in with true to report application readiness on signed V4 diagnostics. Defaults to off; call applicationReady() once the application can serve.
  • onCease: asynchronous cooperative application-work shutdown. Registering it advertises cooperative_cease.v1 on UID-bound V4 diagnostics; Liskov never stops the paid on-chain job.

Test hooks:

  • env: process-env replacement.
  • std: Acurast _STD_ replacement.
  • environment: Acurast environment(name) replacement.
  • identityProvider: fake identity/sign/decrypt provider.
  • fetchImpl: fake network implementation.
  • nowMs, randomBytes: deterministic clock and nonce/digest inputs.
  • setTimeoutImpl, clearTimeoutImpl: deterministic timer harness.

Environment Lookup

Runtime values are resolved from:

  1. The supplied options.env, or process.env.
  2. Acurast _STD_.env.
  3. Acurast environment(name).

Use the runtime accessor after bootstrap because runtime-env and secrets may install values during startup:

const webhookUrl = runtime.env.require("WEBHOOK_URL");
const optionalMode = runtime.env.get("FEATURE_MODE") ?? "default";

require() throws Liskov runtime env <NAME> is required when the value is absent.

Liskov Runtime Env

Liskov jobs receive compact public bootstrap config through LISKOV_BOOTSTRAP (the legacy PROOF_SLIPWAY_BOOTSTRAP and PROOF_SLIPWAY_URL names are no longer read):

{
  "v": 1,
  "u": "https://slipway.example",
  "a": "application-id",
  "p": "64-character-policy-digest",
  "d": "deployment-id",
  "x": {
    "t": "diagnostics-token",
    "h": { "i": 30000, "d": 30000, "to": 1500 }
  }
}

Expanded keys such as slipwayUrl, applicationId, policyDigest, deploymentId, diagnostics.token, and diagnostics.health are also accepted.

When the bootstrap is present, the runtime signs a proof.slipway.runtime-env-request.v1 request and POSTs it to /api/jobs/runtime-env. The response must bind the same application id, policy digest, deployment id, job id, and processor id. Returned values are installed into runtime env before managed secrets are requested.

refreshNow() forces an immediate runtime-env refresh when the bootstrap config exists, then performs one deduped secrets attempt if background secrets are still pending, then refreshes logging. The current v0 periodic runtime-env refresh is internal; Applications should use refreshNow() when they need an explicit reload.

The signed runtime bootstrap is sent to /api/jobs/runtime-bootstrap on the core URL, compiled in as https://runtime.liskov.proof.computer; LISKOV_CORE_URL overrides the compiled-in core URL.

Secrets

Managed secrets are a built-in Liskov runtime capability. Jobs receive compact secret bootstrap config through LISKOV_LOCKBOX_BOOTSTRAP:

{
  "v": 1,
  "u": "https://secrets.liskov.proof.computer",
  "a": "application-id",
  "g": "grant-id",
  "p": "64-character-policy-digest",
  "d": "deployment-id",
  "s": ["secret-id"]
}

Lockbox is the internal name of the managed-secrets service; it survives only in compatibility identifiers such as this environment name and the diagnostic stage ids below, which Applications read or set but never need to learn as a product.

Required

Required mode is the default when secret bootstrap config exists:

const runtime = await bootstrapSlipwayRuntime({
  secrets: { mode: "required" }
});

Bootstrap waits for the secret request, verifies the encrypted payload, installs returned env/file secrets, and fails closed if the request is rejected or the payload does not verify.

Background

Background mode is for Applications that can boot in a locked or degraded mode:

const runtime = await bootstrapSlipwayRuntime({
  secrets: {
    mode: "background",
    retry: {
      initialDelayMs: 0,
      intervalMs: 5_000,
      maxElapsedMs: 60_000,
      maxAttempts: 12
    }
  }
});

Bootstrap returns before the first secret request. The secrets capability reports pending, degraded, failed, or ready, but it is not a readiness blocker because it is not required. refreshNow() performs one immediate attempt while the retry budget is still open. stop() cancels scheduled background retries.

Off

Use secrets: { mode: "off" } for jobs that intentionally ignore secret bootstrap values.

Installation Rules

Env secrets are installed into runtime env by name. An authenticated signed bootstrap is authoritative for its current job and replaces ambient values left by a reused runtime. An env-delivered bootstrap keeps existing values. When a signed grant owns blackbox-log-config, logging buffers until that current config is installed; it never attaches an older job's ambient sink config.

File secrets require the compact bootstrap's file-base field, f. File targets are written below that directory with mode 0600; path traversal outside the base directory is rejected.

Response Encryption Key

The secret request carries the processor's response encryption key, read from _STD_.job.getEncryptionKeys(). The runtime accepts two encrypted-payload envelopes:

Processor key version curveName Decrypted through
P-256 acurast-p256-hkdf-aes-256-gcm-v1 (-v2 on the v2 payload domain) secp256r1 _STD_.signers.secp256r1.decrypt
secp256k1 acurast-secp256k1-hkdf-aes-256-gcm-v1 secp256k1 _STD_.signers.secp256k1.decrypt

A P-256 key is always preferred. The secp256k1 key is used only when the processor exposes no P-256 key, which matches the key Acurast selects for the processor's acknowledgement. A version paired with the other curve's name is refused. When the processor exposes neither key, bootstrap fails with lockbox_response_key_missing.

Logging

Liskov logging is the runtime's built-in encrypted log capability. Blackbox is its internal name, which survives only in the BLACKBOX_* compatibility values below. Application code should call runtime.log() instead of constructing a log writer:

await runtime.log("worker.tick", { processed: 12 }, {
  severity: "info",
  labels: { component: "worker" }
});

const result = await runtime.flush();

The runtime validates and attaches logging after runtime-env and secret installation. If a log is written before logging config is available, the runtime keeps it in the early in-memory buffer. When config appears later, refreshNow() or the next log() drains the buffer into encrypted log records.

The default background logging mode never blocks readiness. Use logging: { mode: "required" } only when missing or invalid logging config must make the Application non-ready. Use logging: { mode: "off" } to drop runtime logs intentionally.

Accepted config shapes:

  • Pre-bound sink: sinkId + jobId + writeUrl + dek, with an optional resumeUrl. This remains the preferred production provisioning mode. Older configs derive /resume only when writeUrl ends in /events.
  • Factory token: factoryToken + baseUrl + dek. The writer self-registers the job-bound sink on first flush and receives the same write, resume, and canonical-chain contract as a pre-bound sink.

Both shapes can be supplied as BLACKBOX_LOG_CONFIG JSON or expanded BLACKBOX_* env values. Records are encrypted locally before upload and posted batches contain no plaintext log messages. Disk spool state defaults to:

$LISKOV_HOME/logging/spool

Every config defaults to the hkdf-sha256-ed25519-v1 writer derivation; newly provisioned configs also record that value explicitly as writerKeyDerivation. Every invocation therefore derives the same Ed25519 request writer from the protected 32-byte log DEK: HKDF-SHA256 uses UTF-8 salt proof.liskov.blackbox.writer-key.v1, UTF-8 info Ed25519, and a 32-byte output interpreted as an Ed25519 seed. This keeps sibling invocations on one canonical append chain while separating the writer key from record encryption. Low-level callers can still supply an explicit signer for an unmarked config; the managed runtime does not use that compatibility override.

When disk spool is unavailable in auto mode, the writer falls back to memory. Before constructing a new batch, the runtime resolves the server's canonical head in either provisioning mode. If another writer advances the sink between that resolution and upload, the runtime consumes the conflict response's head and retries the encrypted pending batch with at most three sequence rebases. The encrypted records themselves are unchanged. Invalid or inconsistent resume, success, or conflict heads fail closed through logging.onError while the spool remains intact. Some Acurast runtimes omit the body of a successful 201 callback: after an accepted write the SDK resolves the signed server head, and after a created factory registration it performs one idempotent replay. Both paths keep the server authoritative and leave the spool intact if the follow-up cannot prove the committed position. Unknown config shapes report through diagnostics and logging.onError; they do not silently degrade to a no-op.

Diagnostics And Health

Runtime diagnostics are best-effort and bounded. When Liskov bootstrap is available and the runtime can authenticate with either a diagnostics token or the Acurast runtime identity provider, diagnostics are POSTed to /api/jobs/runtime-diagnostics as proof.slipway.runtime-diagnostic.v1. Signed-bootstrap jobs do not need a diagnostics token; the request carries a runtime signature, job id, and processor address when identity is available.

Useful stages include:

  • runtime.start
  • slipway.runtime_env.identity
  • slipway.runtime_env.signed
  • slipway.runtime_env.fetch
  • slipway.runtime_env.response
  • slipway.runtime_env.applied
  • lockbox.secret_request.identity
  • lockbox.secret_request.signed
  • lockbox.secret_request.fetch
  • lockbox.secret_request.response
  • lockbox.secret_request.decrypted
  • lockbox.secret_request.installed
  • lockbox.secret_request.retry
  • slipway.logging.attach
  • slipway.logging.write
  • slipway.logging.buffer
  • runtime.health

Local diagnostic callbacks and remote diagnostic sends use a 1.5 second default timeout. Remote diagnostic failures pause further remote diagnostic attempts for 30 seconds so startup, runtime-env, and secret-request flows cannot be blocked by observability.

Health diagnostics start under the same authentication rule as other remote diagnostics. Defaults are a 30 second initial delay and 30 second interval. Compact bootstrap health fields x.h.i, x.h.d, and x.h.to, or the matching expanded fields, override interval, initial delay, and send timeout.

Diagnostics redact string fields that look like tokens, secrets, private keys, signatures, passwords, or authorization values. Count and boolean presence fields are retained.

Readiness And Status

Use status() for redacted readback:

const status = runtime.status();

if (!status.ready) {
  console.error(status.blockers);
}

Status shape:

interface SlipwayRuntimeStatus {
  ok: boolean;
  ready: boolean;
  home: string;
  applicationUid?: string;
  applicationId?: string;
  deploymentId?: string;
  revision?: string;
  blockers: Array<{ capability: string; code: string; message: string }>;
  capabilities: {
    runtimeEnv: CapabilityStatus;
    secrets: CapabilityStatus;
    logging: CapabilityStatus;
    diagnostics: CapabilityStatus;
    switchboard: CapabilityStatus;
  };
}

Capability states are off, pending, ready, degraded, failed, or blocked. A capability blocks readiness only when required=true and state !== "ready".

Current v0 behavior:

  • runtimeEnv is required when the bootstrap config is present under either name.
  • secrets is required only in required mode.
  • logging is required only in required mode.
  • diagnostics is non-fatal and reports ready once the local emitter exists.
  • switchboard is reported as off by this package; Switchboard readiness lives in @proof-computer/slipway-switchboard.

Acurast Host Allowlisting

The runtime does not call _STD_.net.addAllowedHostnames() implicitly. Acurast only admits hosts to the unrestricted outbound whitelist when the deployment owner has configured the required forward and reverse _acu.* DNS TXT proofs for each hostname/IP. Until Liskov owns and documents those records for a host, the runtime must make ordinary network requests and report any network failure through diagnostics.

Testing Fakes

The runtime is designed to be tested without live Acurast spend:

const env: Record<string, string | undefined> = {
  LISKOV_BOOTSTRAP: JSON.stringify({
    v: 1,
    u: "https://slipway.test",
    a: "app",
    p: "1".repeat(64),
    d: "42"
  })
};

const runtime = await bootstrapSlipwayRuntime({
  env,
  identityProvider: fakeIdentityProvider,
  fetchImpl: fakeFetch,
  nowMs: () => 1_000,
  logging: { spoolMode: "memory" },
  setTimeoutImpl: fakeSetTimeout,
  clearTimeoutImpl: fakeClearTimeout
});

Use logging.spoolMode: "memory" in deterministic unit tests. Use secrets.mode: "background" plus fake timers to prove pending/degraded/ready state without sleeping. Use the local diagnostics callback for redacted event assertions.

The repository tests prove runtime-env, required/background/off secrets, factory-token logging, early buffer drain, config refresh, diagnostics, health, DNS-gated no-allowlist behavior, and source-only Acurast examples without artifact pins or live deployment.

Examples

Source-only example ports live under examples/:

  • examples/acurast-env-vars: reads runtime-env values, posts only a redacted env summary, and writes through runtime.log().
  • examples/acurast-fetch: fetches a price payload, posts a webhook payload, and writes a Liskov runtime log.

The Switchboard webserver example lives in public_repos/slipway-switchboard-js/examples/acurast-webserver because Switchboard ingress is optional and stays in a separate adapter package.

These examples are complete for the current no-spend documentation baseline. The next package-cleanup boundary is server-side Turn 6 factory-token product flow alignment, not more selected Acurast example ports.

Security Boundaries

  • Do not put Liskov server control tokens in runtime env or diagnostics.
  • Do not put plaintext runtime secrets in Liskov runtime-env.
  • Runtime secrets must come from the managed-secrets service and be encrypted to the job response encryption key.
  • HTTPS is required for Liskov, secrets, and logging URLs outside local/test hosts unless an explicit insecure override is supplied.
  • Signed runtime-env and secrets protocol v2 requests bind Application UID, compatibility application id, policy digest, deployment id, job id, processor id, nonce, and expiry.
  • Managed-secret encrypted payloads must bind payload digest, request/response fields, and requested secret ids before installation.
  • File-target secrets are written only under the configured base directory.
  • @proof-computer/liskov-runtime runs inside the job TEE. Liskov control plane services, the managed-secrets and logging services, and CLI/server workflows are separate off-TEE systems.
  • This package does not make Switchboard a required dependency. Use @proof-computer/slipway-switchboard only for Liskov-managed Switchboard ingress jobs.

See SECURITY.md for the release checklist.

Package Gates

Run the release gates before tagging:

pnpm install --frozen-lockfile
pnpm typecheck
pnpm test
pnpm build
pnpm pack:dry-run

Encrypted application loader

The ./encrypted-code export verifies an AES-256-GCM payload before loading a self-contained CommonJS module that exports async start(runtime). The caller first completes bootstrapSlipwayRuntime and passes that same handle; the payload must not bootstrap a second runtime. startEncryptedApplication requires a matching, installed, UID/deployment-bound managed secret named by the public descriptor, delivered to LISKOV_CODE_KEY. An ordinary environment value alone is refused. Keys use canonical standard base64 encoding of 32 random bytes.

The processor also needs a working response key for its secret grant: P-256, or secp256k1 when it exposes no P-256 key (see Response Encryption Key). The Android implementation requires Android 12 or later for P-256; a DataEncryption advertisement alone does not establish P-256 support. lockbox_response_key_missing identifies this processor key, while LISKOV_CODE_KEY is the separate application AES key. Follow the encrypted JavaScript guide for processor selection, paused setup and runtime verification.

The non-secret descriptor and encrypted payload belong in the immutable public bootstrap ZIP. The ZIP's attested digest is the authority for both. Ciphertext and plaintext SHA-256 digests, a 12-byte IV, a 16-byte authentication tag, and AAD binding the protocol domain, secret id and plaintext digest are verified before execution. Source is written exclusively in a fresh private directory, loaded through the CommonJS loader, and removed after start returns or fails. The runtime home is created privately when absent, and the loaded module is removed from the CommonJS cache during cleanup. No shared plaintext cache or network code URL is accepted. Do not put secrets or plaintext application code in the public bootstrap or ZIP extras.

Failures emit a bounded application.encrypted_code.refused.<phase> diagnostic before the stable encrypted_code_start_failed fatal event. Exception text, private source and key material are never included in those diagnostics.

Runtime 0.3.30 and Actions v1.3.2 completed the production encrypted path on 6 September 2026: job 160393 verified its managed grant, loaded the payload, and emitted signed application completion. Actions supplies a runtime home inside the processor job directory, where filesystem access is permitted. The capability matrix retains the separate registered V5 public-release boundary. The existing managed-secrets trust boundary still applies: PROOF can access the code key during managed release. This is not a claim of operator-blind execution or a Cargo private-image capability.

V5 file-secret installation

Version 0.3.31 supports authenticated absolute file destinations as well as legacy relative names below fileBaseDir. The default Node installer stages the file group, uses private 0600 files, rejects symlinks and traversal, and recovers interrupted replacements. It applies environment values after successful file installation. File contents preserve whitespace and newlines.

Custom RuntimeFileWriter implementations must provide installGroup(files) with commit-or-rollback behavior for absolute destinations. Existing relative custom writers remain supported. Rebuild deployed artifacts to upgrade the SDK.

SDK 0.3.32 also consumes the optional v2 secrets.customerRequired hint. Required customer groups block readiness; optional-only groups are discovered and loaded in background mode by default, and an absent optional grant does not block startup. An explicit caller secret mode still takes precedence.

SDK 0.3.33 keeps the signed runtime.health loop for a job whose bootstrap delivers no environment (runtimeEnv.enabled: false). Earlier versions dropped the whole runtime config in that case and never checked in after bootstrap, so core reported every such runtime as contact lost. The runtime-env refresh stays off for those jobs; only the check-ins run.

License

From v0.3.34, this package is licensed under the Functional Source License, Version 1.1, ALv2 Future License (SPDX FSL-1.1-Apache-2.0). The licensor is Moose Labs Ltd. You may use, copy, modify, and redistribute the SDK for any purpose other than a Competing Use, as the license defines it. Building and running your own Applications on it is a Permitted Purpose. Each version becomes available under the Apache License, Version 2.0 on the second anniversary of the date it was released.

The change applies from v0.3.34 onward only. Release tags up to and including v0.3.33 remain as they shipped: their package.json declares MIT.

Network prober sample

collectNetworkSample measures the same bounded network ladder as the Cargo runtime against https://liskov-network-prober.fly.dev. Use the challenge token from the probe's authorization; it is sent as the t query parameter. The sample runs for at most 30 seconds, with UDP before streaming downloads and fixed-length zero uploads, then the prober receipt. Transfers do not retain the download body in memory. The URL is pinned; a different proberUrl returns invalid_response evidence.

import { collectNetworkSample, networkSampleOutcomes } from "@proof-computer/liskov-runtime";

const networkSample = await collectNetworkSample({
  token: authorization.challenge,
  startedAtMs: Date.now()
});
const outcomes = networkSampleOutcomes(networkSample);

Collection resolves to the existing NetworkSampleV1 contract with derived metrics. Network failures and unavailable Node modules become failed or unreachable steps; HTTP sampling continues when UDP is unavailable. A sample without a usable receipt still carries its measured legs at low confidence. networkSampleOutcomes returns exactly bandwidth-download, bandwidth-upload and udp-path, including failed-leg bytes and errors, for coverage admission. For offline tests, inject a NetworkTransport with elapsedUs, prepare, udp, download, upload and receipt methods and optional close cleanup. The optional now function supplies monotonic milliseconds to the default transport. This API uses node:https, node:dns/promises and node:dgram; it does not require the global fetch function.

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages