Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
402b5a1
feat: add value-free resolution report via check --json/--explain
domenkozar Jun 8, 2026
91a8579
feat: add value-carrying resolve payload and `secretspec resolve --json`
domenkozar Jun 8, 2026
f927037
feat: add secretspec-ffi crate exposing the narrow C ABI
domenkozar Jun 8, 2026
5f80f53
feat: add shared codegen IR (secretspec::codegen)
domenkozar Jun 8, 2026
d8ed866
refactor: drive the derive macro through the shared codegen IR
domenkozar Jun 8, 2026
07c9f03
feat: add secretspec-py, the Python reference SDK over the C ABI
domenkozar Jun 9, 2026
7dffc98
feat: add `secretspec codegen --lang python` (IR-driven typed accessors)
domenkozar Jun 9, 2026
2a3cbd1
feat: add secretspec-go, the Go SDK via purego
domenkozar Jun 9, 2026
73c2eeb
feat: add secretspec-rb, the Ruby SDK via stdlib Fiddle
domenkozar Jun 9, 2026
0e8ad5f
feat: add secretspec Node.js/TypeScript SDK via koffi
domenkozar Jun 9, 2026
5cc327d
test: add cross-language conformance suite
domenkozar Jun 9, 2026
e046a06
test: add aggregate cross-language conformance runner
domenkozar Jun 9, 2026
10b46a7
refactor: generate typed shapes via JSON Schema + quicktype, not per-…
domenkozar Jun 9, 2026
8e1b31d
ci: run all language SDK suites in CI
domenkozar Jun 9, 2026
4cdbd65
docs: add Python/Go/Ruby/Node.js SDK pages and README section
domenkozar Jun 9, 2026
e3788c4
build(python): package a platform wheel bundling the cdylib
domenkozar Jun 9, 2026
67b0471
build(ruby): package a platform gem bundling the cdylib
domenkozar Jun 9, 2026
cf9d34e
build(go): embed the cdylib via go:embed (behind embed_lib tag)
domenkozar Jun 9, 2026
eb8bbeb
feat(node): switch the Node SDK to a napi-rs addon
domenkozar Jun 9, 2026
792943f
ci: wire per-ecosystem release/publish pipelines
domenkozar Jun 9, 2026
db26b01
test: e2e the schema/quicktype codegen pipeline in all four SDKs
domenkozar Jun 9, 2026
0bd9ca8
docs: add an SDK overview page
domenkozar Jun 9, 2026
ee404ed
docs: add a Language SDKs block to the landing page
domenkozar Jun 9, 2026
4156050
docs: merge the Rust and Language SDKs landing sections into one
domenkozar Jun 9, 2026
082a59e
fix(core): align per-profile schema, harden resolve_json, dedupe codegen
domenkozar Jun 9, 2026
a4ed138
fix(go): validate response, skip null env, verify embedded cdylib
domenkozar Jun 9, 2026
d7828f1
fix(python): validate response, lock dlopen, builder parity
domenkozar Jun 9, 2026
b9a994b
fix(ruby): skip null env, validate response, lock dlopen, builder parity
domenkozar Jun 9, 2026
458a6e9
fix(node): validate response, skip null env, builder parity
domenkozar Jun 9, 2026
49dd2a6
fix(conformance): map the Windows cdylib name in the runner
domenkozar Jun 9, 2026
cbe4633
fix(core): redact credentials from the reported provider URI
domenkozar Jun 9, 2026
ce5ad93
perf(node): resolve off the event loop via loadAsync
domenkozar Jun 9, 2026
e78ef49
fix(sdks): load the most recently built cdylib, not always release
domenkozar Jun 9, 2026
54f0a60
docs: correct the Node "no native build" claim; changelog the fixes
domenkozar Jun 9, 2026
8c6c6c1
fix(core): resolve no_values without materializing values; add report()
domenkozar Jun 10, 2026
f11fbae
fix(sdks): null fields() consistency, as_path cleanup, and report()
domenkozar Jun 10, 2026
79ab0e3
feat(haskell): add the secretspec-hs SDK
domenkozar Jun 10, 2026
6af14bb
fix(core): make value-free resolve/report side-effect-free and surfac…
domenkozar Jun 11, 2026
65c0f7f
fix(go): harden the SDK and switch to the system library distribution…
domenkozar Jun 11, 2026
9fbd7dd
fix(haskell): free the native response under mask/finally
domenkozar Jun 11, 2026
ee59238
test(sdks): release as_path temp files in value-carrying tests
domenkozar Jun 11, 2026
0db108b
refactor(cli): drop the resolve subcommand, keep the contract FFI-only
domenkozar Jun 11, 2026
0d43614
ci: pin Rust via rust-toolchain.toml, scope artifact PR triggers, giv…
domenkozar Jun 11, 2026
d08f967
ci(sdks): free runner disk space before the workspace build
domenkozar Jun 11, 2026
d069295
ci(haskell): free runner disk space before the workspace build
domenkozar Jun 11, 2026
eed82a8
ci: replace retired macos-13 runners with macos-15-intel
domenkozar Jun 11, 2026
5e1be3e
fix(windows): support drive-letter provider paths and Windows SDK builds
domenkozar Jun 11, 2026
de2713a
ci: drop Intel macOS artifacts, move arm macOS legs to macos-latest
domenkozar Jun 11, 2026
21c7a3d
fix(node): install the addon atomically and prebuild it in the SDKs CI
domenkozar Jun 11, 2026
65a2cc2
ci(python): drop the stale UNVALIDATED note, the wheel pipeline has r…
domenkozar Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ jobs:
with:
fetch-depth: 1

# Provide the project devenv so the reviewer can build and run tests
# (e.g. `devenv shell -- cargo test --all`) instead of reviewing blind.
- uses: cachix/install-nix-action@v31
- uses: cachix/cachix-action@v16
with:
name: devenv
- name: Install devenv.sh
run: nix profile install nixpkgs#devenv

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
Expand All @@ -51,7 +60,9 @@ jobs:

Be constructive and helpful in your feedback.

# Optional: pass extra CLI arguments such as a model or tool allowlist
# claude_args: |
# --model claude-opus-4-20250514
# --allowedTools "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
The project devenv is available; you can build and run tests with
e.g. `devenv shell -- cargo test --all` or `devenv test` to verify
suspected issues before reporting them.

claude_args: |
--allowedTools "Bash(devenv:*)"
77 changes: 77 additions & 0 deletions .github/workflows/ffi-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: "FFI cdylib"

# Builds the secretspec-ffi C ABI library for each platform the language SDKs
# bundle. Builds NATIVELY on a per-platform runner rather than cross-compiling,
# because the crate links system libraries (e.g. dbus/keyring on Linux) that
# make cross toolchains painful.
#
# NOTE: This produces development-grade artifacts. Production packaging
# (manylinux compliance for Python wheels, macOS code signing/notarization,
# Windows runtime considerations) is follow-up work tracked with the SDK
# distribution effort.

on:
workflow_dispatch:
push:
tags:
- v**
# PR runs are scoped to changes in the FFI crate or this workflow. Core
# resolver changes are verified on PRs by the devenv-based test.yml and
# sdks.yml; the full matrix here still runs on tags and manual dispatch.
pull_request:
paths:
- "secretspec-ffi/**"
- ".github/workflows/ffi-build.yml"

jobs:
build:
name: ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
artifact: libsecretspec_ffi.so
- target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm
artifact: libsecretspec_ffi.so
- target: aarch64-apple-darwin
runner: macos-latest
artifact: libsecretspec_ffi.dylib
- target: x86_64-pc-windows-msvc
runner: windows-latest
artifact: secretspec_ffi.dll

steps:
- uses: actions/checkout@v5

- name: Install Linux system dependencies
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config

- name: Install Rust (pinned by rust-toolchain.toml)
run: rustup toolchain install

- name: Build cdylib
run: cargo build -p secretspec-ffi --release --target ${{ matrix.target }}

- name: Smoke test the C ABI (Unix)
if: runner.os != 'Windows'
run: |
cc secretspec-ffi/tests/smoke.c \
-I secretspec-ffi/include \
-L target/${{ matrix.target }}/release \
-lsecretspec_ffi -o smoke
LD_LIBRARY_PATH=target/${{ matrix.target }}/release \
DYLD_LIBRARY_PATH=target/${{ matrix.target }}/release \
./smoke

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: secretspec-ffi-${{ matrix.target }}
path: |
target/${{ matrix.target }}/release/${{ matrix.artifact }}
secretspec-ffi/include/secretspec.h
85 changes: 85 additions & 0 deletions .github/workflows/go-embed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: "Go embedded lib"

# Builds the per-platform cdylib the Go SDK embeds (go:embed, behind the
# `embed_lib` build tag) and verifies the embedded build works with no
# SECRETSPEC_FFI_LIB set. The libraries are uploaded as artifacts and attached to
# GitHub releases for users who want a self-contained `-tags embed_lib` build;
# they are never committed to the repo (the Go module proxy does not carry binary
# assets — see RELEASE.md).

on:
workflow_dispatch:
push:
tags:
- v**
# PR runs are scoped to changes in the Go SDK or this workflow. Core
# resolver and FFI changes are verified on PRs by the devenv-based test.yml,
# sdks.yml, and ffi-build.yml; the full matrix here still runs on tags and
# manual dispatch.
pull_request:
paths:
- "secretspec-go/**"
- ".github/workflows/go-embed.yml"

jobs:
embed:
name: ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { target: linux_amd64, runner: ubuntu-latest }
- { target: linux_arm64, runner: ubuntu-24.04-arm }
- { target: darwin_arm64, runner: macos-latest }
- { target: windows_amd64, runner: windows-latest }

steps:
- uses: actions/checkout@v5

- name: Install Linux system dependencies (dbus for keyring)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config

- name: Install Rust (pinned by rust-toolchain.toml)
run: rustup toolchain install
- uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Stage the embedded cdylib
shell: bash
run: bash secretspec-go/scripts/stage-cdylib.sh

- name: Build and smoke test the embedded SDK (no SECRETSPEC_FFI_LIB)
shell: bash
run: |
smoke="$RUNNER_TEMP/embedsmoke"
mkdir -p "$smoke"
cat > "$smoke/main.go" <<'EOF'
package main
import (
"fmt"
secretspec "github.com/cachix/secretspec/secretspec-go"
)
func main() {
v, err := secretspec.ABIVersion()
if err != nil { panic(err) }
fmt.Println("abi", v)
}
EOF
cat > "$smoke/go.mod" <<EOF
module example.com/embedsmoke
go 1.23
require github.com/cachix/secretspec/secretspec-go v0.0.0
replace github.com/cachix/secretspec/secretspec-go => $GITHUB_WORKSPACE/secretspec-go
EOF
cd "$smoke"
go mod tidy
unset SECRETSPEC_FFI_LIB
go run -tags embed_lib .

- uses: actions/upload-artifact@v4
with:
name: go-embed-${{ matrix.target }}
path: secretspec-go/lib/*
85 changes: 85 additions & 0 deletions .github/workflows/haskell-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: "Haskell SDK"

# Builds and tests the Haskell SDK (secretspec-hs) against a freshly built
# cdylib. The SDK links the secretspec-ffi C ABI at build time via the FFI, so
# the cdylib's directory goes on both the linker path (--extra-lib-dirs) and the
# runtime loader path.

on:
workflow_dispatch:
pull_request:
paths:
- "secretspec-hs/**"
- "secretspec-ffi/**"
- "secretspec/**"
- ".github/workflows/haskell-build.yml"
push:
branches: [main]
tags:
- v**

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
# The cdylib + CLI debug build (AWS/GCP/Bitwarden providers) plus the
# Nix store overflows the ~14GB free on a hosted runner.
- name: Free up disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android \
/opt/hostedtoolcache/CodeQL /usr/local/.ghcup /opt/ghc \
/usr/local/share/boost /usr/local/share/powershell
sudo docker image prune --all --force
df -h /
- uses: cachix/install-nix-action@v31
- uses: cachix/cachix-action@v16
with:
name: devenv
- name: Install devenv.sh
run: nix profile install nixpkgs#devenv
- name: Build cdylib + CLI and run the Haskell SDK test-suite
run: |
devenv shell -- bash -c '
set -euo pipefail
cargo build -p secretspec-ffi -p secretspec
target_dir="$(cargo metadata --no-deps --format-version 1 \
| grep -o "\"target_directory\":\"[^\"]*\"" | head -1 | sed "s/.*:\"\(.*\)\"/\1/")"
lib_dir="$target_dir/debug"
export SECRETSPEC_BIN="$lib_dir/secretspec"
cd secretspec-hs
cabal update
# --write-ghc-environment-files lets the codegen test compile the
# quicktype-generated module; SECRETSPEC_BIN lets it run the CLI.
LD_LIBRARY_PATH="$lib_dir:${LD_LIBRARY_PATH:-}" \
cabal test --extra-lib-dirs="$lib_dir" \
--write-ghc-environment-files=always --test-show-details=streaming
'

publish:
name: publish to Hackage
if: startsWith(github.ref, 'refs/tags/v')
needs: [build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: cachix/install-nix-action@v31
- uses: cachix/cachix-action@v16
with:
name: devenv
- name: Install devenv.sh
run: nix profile install nixpkgs#devenv
- name: sdist and upload to Hackage
# Requires the HACKAGE_TOKEN secret. The package links secretspec-ffi at
# build time, so Hackage's build bots cannot compile it (no cdylib); the
# upload still succeeds and the README documents the link requirement.
env:
HACKAGE_TOKEN: ${{ secrets.HACKAGE_TOKEN }}
run: |
devenv shell -- bash -c '
set -euo pipefail
cd secretspec-hs
cabal sdist
cabal upload --publish --token="$HACKAGE_TOKEN" \
dist-newstyle/sdist/secretspec-*.tar.gz
'
59 changes: 59 additions & 0 deletions .github/workflows/node-addon.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: "Node addon"

# Builds the napi-rs Node addon (secretspec.node) per platform and smoke tests
# it. The addon embeds the resolver, so the published npm package needs no
# native build at install time.
#
# NOTE: this uploads a per-platform addon artifact. Full npm distribution
# publishes these as per-platform packages (the pattern @napi-rs/cli automates);
# that publish wiring is the remaining follow-up.

on:
workflow_dispatch:
push:
tags:
- v**
# PR runs are scoped to changes in the Node SDK or this workflow. Core
# resolver changes are verified on PRs by the devenv-based test.yml and
# sdks.yml; the full matrix here still runs on tags and manual dispatch.
pull_request:
paths:
- "secretspec-node/**"
- ".github/workflows/node-addon.yml"

jobs:
addon:
name: ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { target: linux-x64, runner: ubuntu-latest }
- { target: linux-arm64, runner: ubuntu-24.04-arm }
- { target: darwin-arm64, runner: macos-latest }
- { target: win32-x64, runner: windows-latest }

steps:
- uses: actions/checkout@v5

- name: Install Linux system dependencies (dbus for keyring)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libdbus-1-dev pkg-config

- name: Install Rust (pinned by rust-toolchain.toml)
run: rustup toolchain install
- uses: actions/setup-node@v4
with:
node-version: "22"

- name: Build the addon and run the SDK tests
shell: bash
run: |
bash secretspec-node/scripts/build-addon.sh
( cd secretspec-node && node --test )

- uses: actions/upload-artifact@v4
with:
name: node-addon-${{ matrix.target }}
path: secretspec-node/secretspec.node
Loading
Loading