Skip to content

feat(sdk): TinyGo WASM canary builds and spike plan#3063

Draft
pflynn-virtru wants to merge 13 commits intomainfrom
feat/wasm-tinygo-canary
Draft

feat(sdk): TinyGo WASM canary builds and spike plan#3063
pflynn-virtru wants to merge 13 commits intomainfrom
feat/wasm-tinygo-canary

Conversation

@pflynn-virtru
Copy link
Member

@pflynn-virtru pflynn-virtru commented Feb 9, 2026

Summary

  • Add TinyGo WASM canary programs under sdk/experimental/tdf/wasm/ that exercise the stdlib and third-party packages needed for a hybrid WASM TDF core engine
  • Migrate sdk/experimental/tdf/ manifest, assertion, and key-access structs from encoding/json to tinyjson codegen for TinyGo WASM compatibility — includes generated marshal/unmarshal code and updated tests
  • Add tinyjson and zipstream canaries that validate these migrations compile and round-trip correctly under TinyGo
  • Add informational CI workflow (.github/workflows/tinygo-wasm-canary.yaml) that compiles each canary with TinyGo targeting wasip1 — expected to have failures until spike work is complete
  • Add spike plan ADR (docs/adr/spike-wasm-core-tinygo-hybrid.md) documenting the TinyGo hybrid architecture, host crypto ABI (8 functions), go/no-go criteria, and task breakdown
  • Add TDF decrypt benchmarks (sdk/benchmark_test.go) measuring pure decrypt throughput at 1MB–2GB using direct key injection (no KAS dependency)
  • Add experimental TDF Writer encrypt benchmarks (sdk/experimental/tdf/benchmark_test.go) measuring streaming encrypt throughput, single-segment performance, and full TDF assembly
  • Add hostcrypto package (sdk/experimental/tdf/wasm/hostcrypto/) with typed Go wrappers for all go:wasmimport host functions — the WASM-side ABI layer for crypto and I/O
  • Add Wazero host module (sdk/experimental/tdf/wasm/host/) implementing the host side of the crypto/IO ABI — registers "crypto" and "io" modules with Wazero, delegating all crypto to lib/ocrypto. Includes 20 tests covering ABI conformance, round-trip correctness, error paths, and OOB handling.
  • Implement single-segment TDF3 encrypt in WASM — the first real TDF logic running inside the WASM sandbox. All crypto delegated to host via hostcrypto; manifest construction, policy binding (HS256), integrity computation, and ZIP assembly run inside WASM using tinyjson types and zipstream.
  • Add 11 end-to-end encrypt integration tests — compile WASM module, load in wazero, exercise tdf_encrypt: round-trip decrypt, manifest field validation, policy binding, segment/root integrity, UUID format, attributes, empty plaintext, deterministic sizes, and error paths. Includes wazero proc_exit fix for Go 1.25 wasip1 and GC-safety fixes for WASM malloc.

Canary programs

Canary Packages tested Expected
base64hex encoding/base64, encoding/hex pass
zipwrite encoding/binary, hash/crc32, bytes, sort, sync pass
tinyjson tinyjson codegen manifest + assertion round-trip pass
zipstream production zipstream writer: TDF ZIP creation + CRC32 combine + ZIP64 pass
iocontext io, context, strings, strconv, fmt, errors fail
stdjson encoding/json with TDF manifest structs (superseded by tinyjson) fail
wasm full WASM module — go:wasmimport host ABI + tdf package fail

Host crypto ABI

Host function Wazero implementation Tests
random_bytes ocrypto.RandomBytes(n) happy path, OOB write
aes_gcm_encrypt ocrypto.NewAESGcm(key).Encrypt(pt) round-trip, empty key
aes_gcm_decrypt ocrypto.NewAESGcm(key).Decrypt(ct) round-trip, empty key, empty ct, corrupted ct
hmac_sha256 ocrypto.CalculateSHA256Hmac(key, data) vs direct ocrypto, OOB output
rsa_oaep_sha1_encrypt ocrypto.NewAsymEncryption(pem).Encrypt(pt) round-trip, wrong key
rsa_oaep_sha1_decrypt ocrypto.NewAsymDecryption(pem).Decrypt(ct) round-trip, wrong key
rsa_generate_keypair ocrypto.NewRSAKeyPair(bits) PEM validation + round-trip
get_last_error thread-safe string (set/get/clear) retrieval, clear-after-read, truncation, no-error
read_input cfg.Input.Read(buf) data flow, EOF, nil reader
write_output cfg.Output.Write(buf) data flow, nil writer

WASM TDF encrypt (Task 3.1)

Single-segment TDF3 encrypt running entirely inside the WASM sandbox:

Step Operation Implementation
1 DEK generation hostcrypto.RandomBytes(32)
2 Key wrapping hostcrypto.RsaOaepSha1Encrypt(kasPub, dek)
3 Policy construction tinyjson types + MarshalJSON()
4 Policy binding HMAC-SHA256(dek, base64Policy) → hex → base64
5 AES-GCM encrypt hostcrypto.AesGcmEncrypt(dek, plaintext)
6 Segment integrity HMAC-SHA256(dek, cipher) → base64
7 Root signature HMAC-SHA256(dek, segmentSig) → base64
8 ZIP assembly zipstream WriteSegment + Finalize

Encrypt integration tests (11 tests)

Test Validates
TestTDFEncryptRoundTrip Full encrypt → unwrap DEK → AES-GCM decrypt → plaintext matches
TestTDFEncryptManifestFields All manifest fields (version, method, key access, payload, segments)
TestTDFEncryptPolicyBinding HMAC-SHA256 double-encoding matches recomputed binding
TestTDFEncryptSegmentIntegrity Segment hash + root signature match recomputed HMAC values
TestTDFEncryptPolicyUUID UUID v4 format validation
TestTDFEncryptWithAttributes Attributes round-trip through policy JSON
TestTDFEncryptEmptyPlaintext Empty input → 28-byte payload (nonce + tag only)
TestTDFEncryptDeterministicSizes Consistent sizes across encryptions, different ciphertext
TestTDFEncryptErrorInvalidKey Invalid PEM → error message
TestTDFEncryptErrorBufferTooSmall Undersized output buffer → "buffer too small" error
TestTDFEncryptGetErrorClearsAfterRead Error cleared after get_error retrieval

Benchmarks

Measured on a single dev machine (Apple Silicon); numbers are indicative, not normative.

Benchmark Path Throughput
BenchmarkDecrypt/1MB–2GB sdk/benchmark_test.go ~1.4–1.6 GB/s (WriteTo)
BenchmarkStreamDecrypt (100MB, 32KB reads) sdk/benchmark_test.go ~23 MB/s (ReadAt overhead)
BenchmarkWriterEncrypt/1MB–1GB sdk/experimental/tdf/benchmark_test.go ~1.1–1.2 GB/s
BenchmarkWriterWriteSegment (2MB) sdk/experimental/tdf/benchmark_test.go ~1.25 GB/s
BenchmarkWriterAssemble/1MB–100MB sdk/experimental/tdf/benchmark_test.go ~1.0–1.1 GB/s

CI workflow

  • Informational only — not in the ci aggregation job, does not block PRs
  • Matrix strategy with fail-fast: false — all canaries run independently
  • Reports binary size and build/run status in job summary
  • Triggers on changes to sdk/experimental/tdf/**, sdk/internal/zipstream/**, sdk/manifest.go, lib/ocrypto/**

Test plan

  • CI workflow runs successfully (individual canaries may fail as expected)
  • base64hex, zipwrite, tinyjson, and zipstream canaries pass TinyGo compilation and execution
  • All canaries compile with standard Go (go build ./sdk/experimental/tdf/wasm/...)
  • Workflow does not appear in ci aggregation job needs list
  • Decrypt benchmarks pass: cd sdk && go test -bench=BenchmarkDecrypt -short -run=^$ .
  • Experimental writer benchmarks pass: cd sdk/experimental/tdf && go test -bench=Benchmark -short -run=^$ .
  • Wazero host module tests pass: go test -v ./sdk/experimental/tdf/wasm/host/ (20 host ABI tests)
  • WASM encrypt integration tests pass: go test -v ./sdk/experimental/tdf/wasm/host/ -run TestTDFEncrypt (11 end-to-end tests)
  • Full SDK builds: go build ./sdk/...
  • WASM module compiles: GOOS=wasip1 GOARCH=wasm go build ./sdk/experimental/tdf/wasm/

Related: SDK-WASM-1 (Jira)

🤖 Generated with Claude Code

pflynn-virtru and others added 2 commits February 9, 2026 11:35
ADR documenting the TinyGo hybrid WASM architecture spike (SDK-WASM-1),
including host crypto ABI, go/no-go criteria, and task breakdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Flynn <pflynn@virtru.com>
@github-actions github-actions bot added comp:ci Github Actions Work comp:sdk A software development kit, including library, for client applications and inter-service communicati docs Documentation size/l labels Feb 9, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @pflynn-virtru, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request lays the groundwork for a significant architectural shift by exploring the feasibility of a TinyGo-compiled WebAssembly (WASM) core engine for TDF operations. It introduces a set of targeted canary programs to assess TinyGo's compatibility with crucial Go standard library components and establishes a detailed spike plan. The primary aim is to validate a hybrid approach where cryptographic primitives are delegated to the host environment, while core TDF logic resides within a compact and portable WASM module, paving the way for enhanced flexibility and deployment options.

Highlights

  • TinyGo WASM Canary Programs: Introduced several TinyGo WASM canary programs under 'sdk/experimental/tdf/wasm/' to test the compatibility and functionality of various standard library packages (e.g., encoding/base64, encoding/hex, io, context, encoding/json, hash/crc32) essential for building a hybrid WASM TDF core engine.
  • Informational CI Workflow: Implemented a new informational CI workflow ('.github/workflows/tinygo-wasm-canary.yaml') that compiles and runs these TinyGo canaries targeting 'wasip1'. This workflow is non-blocking and provides early feedback on TinyGo's behavior with specific TDF-related code patterns, with some expected failures for certain canaries.
  • Spike Plan Architectural Decision Record (ADR): Added a comprehensive Architectural Decision Record ('docs/adr/spike-wasm-core-tinygo-hybrid.md') detailing a 2-week spike plan. This ADR outlines the objective, go/no-go criteria, proposed hybrid architecture, host crypto ABI (8 functions), task breakdown, measurement strategies, and identified technical risks for validating a TinyGo-compiled WASM module for TDF3 single-segment encrypt/decrypt.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • docs/adr/spike-wasm-core-tinygo-hybrid.md
    • Added a new Architectural Decision Record (ADR) titled 'SDK-WASM-1: Spike — TinyGo Hybrid WASM Core Engine'.
    • Defined the objective to validate TinyGo-compiled WASM for TDF3 single-segment encrypt/decrypt with host-delegated crypto.
    • Established five clear Go/No-Go criteria for the spike, covering compilation, host function interoperability, binary size, TDF validity, and performance.
    • Detailed the proposed hybrid architecture, illustrating the separation of WASM-internal logic (e.g., manifest handling, ZIP writing) from 8 host-imported crypto functions (e.g., AES-GCM, RSA-OAEP, HMAC-SHA256).
    • Specified the Host Function ABI conventions for data exchange (shared linear memory), parameter types (ptr, len pairs), error reporting, and output sizing.
    • Outlined a 4-phase task breakdown for the 10-day spike, including scaffolding, adapting manifest structs and zipstream, implementing the Wazero host crypto interface, and developing TDF encrypt with round-trip validation.
    • Identified explicitly out-of-scope items for the spike, such as NanoTDF, EC key wrapping, and in-WASM decrypt.
    • Listed dependencies and prerequisites, including TinyGo, Wazero, tinyjson codegen, and wasm-opt.
    • Analyzed key technical risks (e.g., tinyjson compatibility, encoding/binary issues, shared memory pointer fragility) and proposed mitigation strategies.
    • Provided an estimated effort breakdown for each phase and a vision for future ABI evolution to support EC-wrapped TDFs.
  • sdk/experimental/tdf/wasm/base64hex/main.go
    • Added a new TinyGo canary program to verify the correct round-trip encoding and decoding functionality of 'encoding/base64' and 'encoding/hex', which are crucial for TDF policy and assertion hash encoding.
  • sdk/experimental/tdf/wasm/iocontext/main.go
    • Added a new TinyGo canary program to test the compatibility of various standard library packages under TinyGo, including 'io' (Reader, Writer, ReadFull, MultiReader), 'context' (cancellation), 'strings' (Contains, ToLower, Split), 'strconv' (Itoa, Atoi), 'fmt' (Sprintf), and 'errors' (Errorf, Is), all of which are extensively used in TDF logic.
  • sdk/experimental/tdf/wasm/stdjson/main.go
    • Added a new TinyGo canary program that attempts to marshal and unmarshal TDF manifest structs using the standard 'encoding/json' package. This canary is explicitly expected to fail under TinyGo due to its known limitations with 'reflect' features, serving as a baseline for the planned 'tinyjson' integration.
  • sdk/experimental/tdf/wasm/wasmimport/main.go
    • Added a new TinyGo canary program to validate the compilation of 'go:wasmimport' directives for 8 crypto host functions and 'go:wasmexport' directives for 'malloc', 'free', and 'tdf_encrypt'. This program demonstrates the core pattern for the hybrid WASM architecture, ensuring TinyGo can correctly handle host-guest function interfaces.
  • sdk/experimental/tdf/wasm/zipwrite/main.go
    • Added a new TinyGo canary program to test the functionality of 'encoding/binary' (Write, Read with LittleEndian), 'hash/crc32' (ChecksumIEEE, incremental CRC), 'sort.Ints', 'sync.Mutex', and 'bytes.Buffer' composition. These operations are fundamental to the 'zipstream' package, which is responsible for writing TDF ZIP archives.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/tinygo-wasm-canary.yaml
Activity
  • The pull request was opened to introduce the initial set of TinyGo WASM canary builds and a detailed spike plan.
  • An informational CI workflow ('tinygo-wasm-canary.yaml') has been configured to automatically compile and execute these canary programs, providing early feedback on TinyGo compatibility without blocking the PR.
  • Canary programs for 'base64hex' and 'zipwrite' are expected to compile and pass, while 'iocontext' and 'stdjson' are anticipated to fail, as outlined in the PR description, to gather critical data for the spike.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Go code, now WASM bound, TinyGo makes it small and fast, New frontiers are found.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive spike plan (ADR) for a TinyGo-based WASM core engine and adds several canary programs to test the compatibility of necessary Go standard library packages with TinyGo. The ADR is well-structured and detailed, covering architecture, ABI, risks, and a task breakdown. The canary programs are good initial steps to de-risk the effort.

My review focuses on improving the clarity of the ADR and addressing a potential memory safety issue in the wasmimport canary. I've suggested a clarification in the ADR's objective to align it better with the documented scope. I've also recommended adding a crucial comment to the wasmMalloc implementation to highlight its dependency on the -gc=leaking build flag for memory safety, which is critical for future maintenance.

Comment on lines 44 to 45
buf := make([]byte, size)
return uint32(uintptr(unsafe.Pointer(&buf[0])))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation of wasmMalloc has a potential memory safety issue. The buf slice is allocated within the function, and returning a pointer to its underlying data can lead to a dangling pointer if the garbage collector reclaims buf after the function returns. While this is mitigated by compiling with the -gc=leaking flag as mentioned in the ADR, this critical dependency is not apparent from the code itself. For better maintainability and to prevent accidental misuse, I recommend adding a comment explaining why this is safe under the specific build conditions and highlighting the intentional memory leak.

	buf := make([]byte, size)
	// NOTE: This leaks memory. This is only safe because the module is compiled
	// with the `-gc=leaking` flag, which prevents the garbage collector from
	// reclaiming the memory.
	return uint32(uintptr(unsafe.Pointer(&buf[0])))

## Objective

Validate that a TinyGo-compiled WASM module can perform TDF3 single-segment
encrypt/decrypt with all crypto delegated to host functions, producing output
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The objective states encrypt/decrypt, but the scope of the spike seems to be focused on implementing encryption within the WASM module and then validating the output using the existing Go SDK for decryption. The 'Explicitly Out of Scope' section also mentions 'Decrypt inside WASM' is for a future milestone (M2). To better reflect the spike's goal, consider clarifying that only encryption will be performed by the WASM module by removing /decrypt.

Suggested change
encrypt/decrypt with all crypto delegated to host functions, producing output
encrypt with all crypto delegated to host functions, producing output

@github-actions
Copy link
Contributor

github-actions bot commented Feb 9, 2026

X-Test Failure Report

…e logic

- Removed `wasmimport` module and redundant crypto directives.
- Consolidated `calculateSignature` logic into `writer.go` and removed it from `manifest.go`.
- Updated TinyGo canary workflow to reflect WASM module restructuring.
- name: "Report result"
if: always()
run: |
BUILD="${{ steps.build.outcome }}"

Check notice

Code scanning / zizmor

code injection via template expansion Note

code injection via template expansion
@github-actions
Copy link
Contributor

github-actions bot commented Feb 9, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 158.295972ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 84.349628ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 370.740028ms
Throughput 269.73 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 38.084350774s
Average Latency 378.226999ms
Throughput 131.29 requests/second

@github-actions
Copy link
Contributor

github-actions bot commented Feb 9, 2026

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 184.733222ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 117.453566ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 369.118001ms
Throughput 270.92 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 40.022505123s
Average Latency 398.910648ms
Throughput 124.93 requests/second

pflynn-virtru and others added 2 commits February 12, 2026 14:43
Adds self-contained decrypt benchmarks that construct valid TDFs
programmatically and inject payload keys directly, bypassing KAS.
Covers 1MB–2GB WriteTo path and 100MB streaming Read() path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Flynn <pflynn@virtru.com>
Benchmarks for the experimental streaming TDF Writer covering:
- End-to-end encrypt (NewWriter + WriteSegment + Finalize)
- Single segment encrypt throughput (WriteSegment only)
- Full TDF assembly (segments + finalize bytes)
Sizes: 1MB, 100MB, 1GB (short-mode skippable).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paul Flynn <pflynn@virtru.com>
@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 208.100912ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 103.652178ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 377.780866ms
Throughput 264.70 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 39.015039822s
Average Latency 388.838384ms
Throughput 128.16 requests/second

…ibility

Replace reflection-based encoding/json with tinyjson (CosmWasm fork) codegen
for manifest, assertion, and policy structs in the TDF write path. This is a
prerequisite for the WASM core engine spike (SDK-WASM-1) since encoding/json
panics at runtime under TinyGo.

Changes:
- Add tinyjson codegen for manifest.go (13 types) and assertion_types.go (3 types)
- Change KeyAccess.PolicyBinding from interface{} to concrete PolicyBinding type
- Replace json.Marshal with .MarshalJSON() in writer.go, key_access.go, assertion.go
- Move Assertion/Statement/Binding structs to assertion_types.go for codegen
- Drop polymorphic Statement.Value UnmarshalJSON (reader concern, out of WASM scope)
- Add tinyjson TinyGo canary with manifest/policy/assertion round-trip validation
- Add wasm/Makefile with toolcheck, build, run, generate targets
- Add wasm/README.md with TinyGo/tinyjson/wasmtime install instructions

Canary results: tinyjson module compiles to 62KB raw / 29KB gzipped WASM,
all round-trip tests pass under wasmtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 147.955649ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 71.833559ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 364.34748ms
Throughput 274.46 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 38.763645413s
Average Latency 385.728778ms
Throughput 128.99 requests/second

…r WASM

Copy production zipstream writer code (5 files from sdk/internal/zipstream/)
into a standalone canary module and verify it compiles and runs correctly
under TinyGo WASM. This completes Phase 1 (Foundation) of the WASM core
engine spike (SDK-WASM-1).

The canary exercises:
- Single-segment TDF ZIP creation (header + manifest + central directory)
- Multi-segment out-of-order writing (3 segments in order 2, 0, 1)
- ZIP64 mode (ZIP64 EOCD + locator signatures)
- CRC32 combine (multi-part checksum matches direct computation)

Key finding: time.Time and time.Now() work correctly under TinyGo — the only
identified risk for zipstream compatibility.

Binary size: 113KB raw / 59KB gzipped (well under 300KB budget).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

X-Test Failure Report

opentdfplatform5SPVSE.dockerbuild
cukes-report
✅ js-v0.9.0

Use grouped redirects ({ cmd1; cmd2; } >> file) instead of individual
redirects to satisfy shellcheck/actionlint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
if: always()
run: |
BUILD="${{ steps.build.outcome }}"
RUN="${{ steps.run.outcome }}"

Check notice

Code scanning / zizmor

code injection via template expansion Note

code injection via template expansion
@github-actions
Copy link
Contributor

X-Test Failure Report

@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 198.401685ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 100.205609ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 369.525036ms
Throughput 270.62 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 40.838386268s
Average Latency 407.154076ms
Throughput 122.43 requests/second

@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 198.31669ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 98.752819ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 374.098817ms
Throughput 267.31 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 41.356875227s
Average Latency 412.300025ms
Throughput 120.90 requests/second

Document the three I/O models evaluated (WASM-drives, host-drives,
hybrid) and recommend hybrid streaming I/O for M2 with read_input
and write_output host imports. Update ABI evolution to 13 functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 189.177942ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 92.88032ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 368.901947ms
Throughput 271.07 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 39.122868158s
Average Latency 389.627987ms
Throughput 127.80 requests/second

pflynn-virtru and others added 2 commits February 13, 2026 08:23
Move raw go:wasmimport declarations out of wasm/main.go into a dedicated
hostcrypto package with idiomatic Go APIs ([]byte/string params, error
returns). Wraps all 8 crypto host functions plus 2 streaming I/O hooks
(read_input, write_output) for the M2 hybrid I/O architecture.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the host side of the WASM crypto/IO ABI using Wazero. The host
package registers "crypto" and "io" modules that fulfill the go:wasmimport
calls from the hostcrypto guest package, delegating all crypto operations
to lib/ocrypto.

Host functions: random_bytes, aes_gcm_encrypt/decrypt, hmac_sha256,
rsa_oaep_sha1_encrypt/decrypt, rsa_generate_keypair, get_last_error,
read_input, write_output.

Includes 20 tests covering ABI conformance (programmatic WASM module
with matching imports), happy-path round-trips, error paths (bad keys,
corrupted ciphertext, wrong-key decrypt, OOB writes, nil I/O), error
state lifecycle, and truncation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 187.24255ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 99.21437ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 364.564433ms
Throughput 274.30 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 38.628814291s
Average Latency 384.263386ms
Throughput 129.44 requests/second

pflynn-virtru and others added 2 commits February 13, 2026 10:24
Replace the tdf_encrypt stub with a complete single-segment TDF3 encrypt
path running inside the WASM sandbox. All crypto is delegated to the host
via hostcrypto; manifest construction, policy binding, HS256 integrity,
and ZIP assembly run inside WASM using tinyjson types and zipstream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 11 integration tests that compile the WASM module, load it in
wazero, and exercise tdf_encrypt end-to-end: round-trip decrypt,
manifest field validation, policy binding, segment/root integrity,
UUID format, attributes, empty plaintext, deterministic sizes, and
error paths.

Fix Go 1.25 wasip1 proc_exit(0) closing the module by using wazero's
FunctionExporter to provide real WASI with a custom proc_exit that
panics (non-sys.ExitError) instead of closing. Fix GC-safety in
malloc by keeping allocations reachable, and copy data in
ptrToString/ptrToBytes instead of using raw unsafe references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 201.619653ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 95.6534ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 359.869381ms
Throughput 277.88 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 38.669671496s
Average Latency 384.960191ms
Throughput 129.30 requests/second

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:ci Github Actions Work comp:sdk A software development kit, including library, for client applications and inter-service communicati docs Documentation size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant