ops

package
v0.2.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: MPL-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package ops hosts chassis-core op handlers that consume the per-tenant secret store. These are computed-secret ops: they read cleartext from op.Secrets (via context), compute a digest or signature in-process, and write the **non-secret derived value** back into the response envelope. The cleartext is consumed once inside the op and goes nowhere else.

See internal docs/todo-secret-store.md §4.2 for the substitution-vs- computation split.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BasicAuthEncode

func BasicAuthEncode(ctx context.Context, opName string, in, _ []byte) (event.Payload, error)

BasicAuthEncode is the handler for `txco://basic-auth-encode`. It produces the `base64(user:password)` value used by HTTP Basic auth (RFC 7617), with the password coming from op.Secrets.

WITH parameters (op.Meta):

secrets.password.secret = "TWILIO_AUTH_TOKEN"  // required
user                    = "AC1234567890"        // required
output_path             = "_txc.computed.basic_auth"  // default

The handler writes the encoded value (NOT the cleartext) at output_path. Downstream ops set the Authorization header as `Basic <encoded>` — typically via a `secrets.headers.authorization` declaration with `format = "Basic {output_path-value}"`, but since the encoded value is not itself a secret, simpler: just a normal SET that interpolates the envelope value into the header.

Cleartext is consumed inside this function and never leaves it. The base64 encoding is one-way only in the sense that base64- decoding reveals the cleartext — DO NOT trace this output as "non-secret"; it IS a wire credential. The op writes it at _txc.computed.* by default, where the operator chooses how to route it.

func Copy

func Copy(ctx context.Context, _ string, in, _ []byte) (event.Payload, error)

Copy is the handler for `txco://copy`. It reads a value from one envelope path and writes it to another, with optional encoding.

This is the chassis-side answer to "txcl SET RHS is literal-only" (the constraint that forces `txco://route` to exist in Go). When a rule needs to move an envelope field — e.g. "the response body for this web request lives at .text, please put it at _txc.web.res.body" — Copy is the primitive.

WITH parameters (op.Meta):

from    = ".text"                 (required: source path on input envelope)
to      = "_txc.web.res.body"     (required: destination path on response)
encode  = "base64"                (optional: "base64" | "" — default "")
default = "fallback value"        (optional: literal substituted when
                                  the source path is empty/missing)

Path syntax follows gjson on read (a leading "." is optional and stripped) and sjson on write. When the source path is absent or resolves to an empty value AND `default` is set, the literal `default` value is used as the source instead — letting one rule express "use query param if present, else fall back to this." Without `default`, an empty source produces an empty destination (no failure). A missing `from` or `to` parameter at the WITH level IS an authoring error and fails loud.

func HMACSign

func HMACSign(ctx context.Context, opName string, in, _ []byte) (event.Payload, error)

HMACSign is the handler for `txco://hmac-sign`. It HMACs an envelope-path value with a named secret key and writes the digest at a declared output path.

WITH parameters (op.Meta):

secrets.key.secret  = "WEBHOOK_HMAC"   // required: NAME in op.Secrets
algorithm           = "sha256"         // sha256 (default) | sha512
input_path          = "body"           // gjson path on op.Input
output_path         = "_txc.computed.sig"  // sjson path on the response
encoding            = "hex"            // hex (default) | base64

The handler reads `op.Secrets["WEBHOOK_HMAC"]` (the splice puts it there during processor.Run), computes `HMAC-<alg>(secret, gjson.Get(op.Input, input_path).Raw)`, and writes the digest into the response at output_path. The response is JSON; output_path defaults to `_txc.computed.hmac` if absent.

Cleartext is consumed inside this function and never leaves it — the digest is the safe-to-publish artifact (one-way function of input+key).

func HMACVerify

func HMACVerify(ctx context.Context, opName string, in, _ []byte) (event.Payload, error)

HMACVerify is the handler for `txco://hmac-verify`. It recomputes an HMAC over an envelope-path value with a named secret key and constant-time-compares it to an expected signature carried on the envelope, writing a boolean result at output_path.

It is the verification counterpart to txco://hmac-sign, and it lives as an op (not a txcl function) for two reasons functions can't satisfy: the keyed HMAC needs the per-op secret bag (txcl functions never see it), and the comparison must be constant-time (a txcl `==` short-circuits and leaks timing). This is the primitive behind signed-webhook verification — Stripe / GitHub / Shopify / Slack all use minor variants of HMAC-over-body.

Gate it with a WHEN like any op; it only runs when its rule fires. It adds `sig_valid` to the response so a later rule can branch, e.g.:

WHEN ._txc.computed.sig_valid != true
  EXEC "txco://..."   # reject / 401

WITH parameters (op.Meta):

secrets.key.secret = "STRIPE_WEBHOOK_SECRET"   // required: NAME in op.Secrets
algorithm          = "sha256"                  // sha256 (default) | sha512
input_path         = "verify.signed"           // gjson path to the signed data
expected_path      = "verify.v1"               // required: gjson path to the expected sig
encoding           = "hex"                     // hex (default) | base64 (of the expected sig)
output_path        = "_txc.computed.sig_valid" // sjson path for the bool result

String inputs are hashed as their literal (unquoted) value, so a scheme that signs a constructed string like Stripe's "t.body" works; object/array inputs use the raw JSON bytes (preserving whitespace and key order, which is what vendors sign).

Config problems (missing secret ref or expected_path, unmaterialized secret, bad algorithm/encoding) return an error. A missing, empty, or malformed expected signature is NOT an error — it's a failed verification, so the op emits sig_valid=false (fail closed).

The op emits ONLY the boolean — never the recomputed digest, which is itself a valid signature and must not leak into the envelope/trace.

func WebRender

func WebRender(ctx context.Context, _ string, in, _ []byte) (event.Payload, error)

WebRender is the handler for `txco://web-render`. It reads a value from a source envelope path, optionally transforms it (raw / HTML wrap / markdown-to-HTML), base64-encodes it, and writes the result into the web-response shape `_txc.web.res.*` plus `_txc.halt = true`. Designed for the "scope 200 renders the answer that scope 100 produced" pattern.

WITH parameters (op.Meta):

source        = ".text"                          (optional, default ".text")
content_type  = "text/plain; charset=utf-8"      (optional, default
                                                  matches the wrap mode)
status        = 200                              (optional, default 200)
wrap          = "raw"                            (optional: "raw" |
                                                  "html" | "markdown-to-html")

`wrap` modes:

  • "raw" — verbatim bytes. Default content-type "text/plain; charset=utf-8".
  • "html" — wrap the (HTML-escaped) source in a minimal `<pre>` document. Default content-type "text/html; charset=utf-8".
  • "markdown-to-html" — render the source as CommonMark via goldmark. Default content-type "text/html; charset=utf-8".

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL