Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 4 additions & 16 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,11 @@ sboms:
- id: archive
artifacts: archive

# Binaries are published to GCP Artifact Registry (the generic `dist` repo) by the
# release workflow (gcloud artifacts generic upload), fronted by get.operatorstack.systems.
# GoReleaser only builds + checksums + SBOMs; it does NOT create a GitHub Release.
release:
github:
owner: operatorstack
name: interlock
# v0.1.0 is the first release; treat a missing prior tag gracefully.
mode: replace
footer: |
## Protocol versions

| Contract | Version |
| --- | --- |
| policy protocol | `interlock.policy.v1` |
| effect protocol | `interlock.effect.v1` |
| receipt schema | `interlock.receipt.v1` |

Verify a downloaded archive against `checksums.txt`, and verify build
provenance with `gh attestation verify <archive> --repo operatorstack/interlock`.
disable: true

changelog:
use: github
Expand Down
10 changes: 5 additions & 5 deletions UPSTREAM.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"files": {
".gitattributes": "3d38cf98dcc69b2af4941b76ed3f04e51273fdbd4fc54032e88cf3223b4b9198",
".goreleaser.yml": "cdb7f4f950f7e70c0052205966cb11ef7b9a0b270ff03a670deba696cf1c61b8",
".goreleaser.yml": "ad08b869ad32652522cef430ba556a86d09a43ea53b5a3935425204dcedb8b33",
"LICENSE": "bd17d47aefaa7406616179288058001b6532881a2517254fe668d7e9c4965cfb",
"README.md": "39b4cc851a57c654132a73b84d594e61c8a568fd3aed26d86e503133dcdb84c8",
"assets/interlock-boundary.png": "9ae73098102d0589bf1bb912af6d39df4d1465eb93e8cea5b7e982e6fa79ef51",
Expand All @@ -27,7 +27,7 @@
"clients/schema/interlock.schema.json": "b637af7ab11b324f9b018656942552858143b412e5083d18285abadc6d056eba",
"clients/typescript/examples/decision-request.ts": "0a398c305f1fc89b7d0c70c68e34f56c170ba0ee456e0447103c0419c50ad159",
"clients/typescript/examples/parity.ts": "2d73ad5d3c9f2b87bf3755fd029f449afcfcc3dd820877f02ae516228196a1b1",
"clients/typescript/package.json": "d6b747a44a20a2377274e7f5cc12bf292fdec10f60fb7c099a17e3b3bd6f0837",
"clients/typescript/package.json": "91cf220bb3aa4e02c426231d04b32207f5ba10cd92d07812e67f16073690e3bb",
"clients/typescript/src/canonical.ts": "be376928b4563f998a5879201a9cc36407b9c13218ed6357722424e044d1247b",
"clients/typescript/src/index.ts": "b7ccd06a0bfb6e938ff88746ba48b3179b1b855ab6523e9f749658ad514e9728",
"clients/typescript/src/protocol.ts": "a5413e22897330135591f8c44a24eb64cdbfea7762f3f1d2e0866e1424ece145",
Expand Down Expand Up @@ -92,8 +92,8 @@
"examples/release-manifest/publish_test.go": "7594fc7ff5a2abaf3216c74879c8d5873b636f8091d532c39d93971a276f4f4c",
"examples/repository-policy/policy.go": "8c7fe12c487c1369d5ce8ae24e647e050557cd2bf29c56d4010b782603debbd1",
"go.mod": "a9a846b064eac2e330c18198dae19044e438bff31dcb26d928cdb2f9b5cae3e1",
"install.ps1": "ada3f94562569929446dd6ca200f993854fa10081785e3ad1a09db285dacca6a",
"install.sh": "7d62cccc9b35280490c3332279743050957ab7e648b4b115c86211ba8995ab4e",
"install.ps1": "675ffcba0a61ae3cfd87c821ccb13e310a4b96d56272db6167e2b75efb4fdaf3",
"install.sh": "c322f7b8d532d63aa6a2fc1953e972eb7952d7c40ee925db2146aab37deeb3e2",
"interlock.go": "de4ff7ee8dd15ab12d0bea387b66ad6e7abfbb66553839ecc0befc32ec8fb606",
"interlock_test.go": "06b56780f7ae90fe12b055bf426aab8b87ed4fe174698a49d729bdc6484299e2",
"ir/ir.go": "8765290a06278981beff40410092c63e0df3b1561e4cbd7e6c63217f1213390d",
Expand All @@ -117,7 +117,7 @@
"generator": "operatorstack/interlock:project-upstream",
"schema_version": 1,
"source": {
"commit": "15a45d5d730690e825b3c9cf1de077ec876a0c2b",
"commit": "0c891b5d90548ec81d5f1bafe9dd63e06a5df2b2",
"path": "labs/21-interlock",
"repository": "operatorstack/intelligence-flow"
}
Expand Down
1 change: 0 additions & 1 deletion clients/typescript/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "@operatorstack/interlock",
"version": "0.1.0",
"private": true,
"description": "Generated protocol types and canonical encoder for Interlock (interlock.spec.v1 / interlock.policy.v1). Data types only — enforcement stays the Go executable.",
"license": "Apache-2.0",
"type": "module",
Expand Down
139 changes: 48 additions & 91 deletions install.ps1
Original file line number Diff line number Diff line change
@@ -1,96 +1,53 @@
<#
.SYNOPSIS
Interlock installer (Windows) — no Go toolchain required.

.DESCRIPTION
Downloads a pinned prebuilt release, verifies its SHA-256 checksum, installs
interlock.exe, adds the install directory to the user PATH, then runs
`interlock doctor` and the repository-policy demo. Fails closed on a checksum
mismatch.

irm https://raw.githubusercontent.com/operatorstack/interlock/main/install.ps1 | iex

.PARAMETER Version
Release tag to install. Defaults to $env:INTERLOCK_VERSION, else latest.
.PARAMETER InstallDir
Install directory. Defaults to $env:INTERLOCK_INSTALL_DIR, else
%LOCALAPPDATA%\interlock\bin.
#>
[CmdletBinding()]
param(
[string]$Version = $env:INTERLOCK_VERSION,
[string]$InstallDir = $env:INTERLOCK_INSTALL_DIR
)

$ErrorActionPreference = 'Stop'
$Repo = 'operatorstack/interlock'
$Binary = 'interlock'

function Info($m) { Write-Host "interlock-install: $m" }

# --- detect arch (Windows amd64 only) ------------------------------------
$arch = switch ($env:PROCESSOR_ARCHITECTURE) {
'AMD64' { 'amd64' }
default { throw "unsupported architecture: $($env:PROCESSOR_ARCHITECTURE) (only windows/amd64 is published)" }
}
$os = 'windows'

# --- resolve version ------------------------------------------------------
if ([string]::IsNullOrEmpty($Version)) {
Info 'resolving latest release'
$latest = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -Headers @{ 'User-Agent' = 'interlock-install' }
$Version = $latest.tag_name
if ([string]::IsNullOrEmpty($Version)) { throw 'could not resolve latest release tag' }
# interlock installer (Windows) — rendered by distribution/render.mjs, do not edit by hand.
#
# irm https://get.operatorstack.systems/interlock/install.ps1 | iex
#
# Toolchain-free: downloads a prebuilt, checksum-verified binary from OperatorStack's
# GCP Artifact Registry, fronted by get.operatorstack.systems. All-GCP.
#
# Env overrides: INTERLOCK_VERSION (pin), INTERLOCK_INSTALL_DIR (location).
$ErrorActionPreference = "Stop"

$binary = "interlock"
$getHost = "get.operatorstack.systems"
$version = [Environment]::GetEnvironmentVariable("INTERLOCK_VERSION")
$dir = [Environment]::GetEnvironmentVariable("INTERLOCK_INSTALL_DIR")

$arch = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { throw "unsupported architecture" }

if (-not $version) {
$latest = Invoke-RestMethod -Uri "https://$getHost/$binary/latest"
$version = $latest.version
if (-not $version) { throw "could not resolve latest version" }
}
Info "installing $Binary $Version ($os/$arch)"
Write-Host " installing $binary $version (windows/$arch)"

$archive = "${Binary}_${Version}_${os}_${arch}.zip"
$base = "https://github.com/$Repo/releases/download/$Version"

# --- download + verify ----------------------------------------------------
$tmp = Join-Path $env:TEMP ("interlock-" + [System.Guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $tmp -Force | Out-Null
$tmp = New-Item -ItemType Directory -Path (Join-Path $env:TEMP ([guid]::NewGuid()))
try {
$archivePath = Join-Path $tmp $archive
$sumsPath = Join-Path $tmp 'checksums.txt'
Invoke-WebRequest -Uri "$base/$archive" -OutFile $archivePath -UseBasicParsing
Invoke-WebRequest -Uri "$base/checksums.txt" -OutFile $sumsPath -UseBasicParsing

$want = (Select-String -Path $sumsPath -Pattern ([regex]::Escape($archive)) |
Select-Object -First 1).Line -split '\s+' | Select-Object -First 1
if ([string]::IsNullOrEmpty($want)) { throw "no checksum for $archive in checksums.txt" }
$got = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash.ToLower()
if ($want.ToLower() -ne $got) { throw "checksum mismatch for $archive (want $want, got $got)" }
Info 'checksum verified'

# --- install ------------------------------------------------------------
if ([string]::IsNullOrEmpty($InstallDir)) {
$InstallDir = Join-Path $env:LOCALAPPDATA 'interlock\bin'
$archive = "${binary}_${version}_windows_${arch}.zip"
$base = "https://$getHost/$binary/dl/$version"
Invoke-WebRequest -Uri "$base/$archive" -OutFile (Join-Path $tmp $archive)
Invoke-WebRequest -Uri "$base/checksums.txt" -OutFile (Join-Path $tmp "checksums.txt")

$want = (Select-String -Path (Join-Path $tmp "checksums.txt") -Pattern ([regex]::Escape($archive)) |
ForEach-Object { ($_ -split '\s+')[0] } | Select-Object -First 1)
if (-not $want) { throw "no checksum listed for $archive" }
$got = (Get-FileHash -Algorithm SHA256 -Path (Join-Path $tmp $archive)).Hash.ToLower()
if ($want.ToLower() -ne $got) { throw "checksum mismatch — refusing to install" }
Write-Host " checksum verified"

Expand-Archive -Path (Join-Path $tmp $archive) -DestinationPath $tmp -Force
if (-not $dir) { $dir = Join-Path $env:LOCALAPPDATA "$binary\bin" }
New-Item -ItemType Directory -Force -Path $dir | Out-Null
Move-Item -Force -Path (Join-Path $tmp "$binary.exe") -Destination (Join-Path $dir "$binary.exe")
Write-Host " installed to $dir\$binary.exe"

$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$dir*") {
[Environment]::SetEnvironmentVariable("Path", "$userPath;$dir", "User")
Write-Host " added $dir to your PATH (restart your shell)"
}
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
Expand-Archive -Path $archivePath -DestinationPath $tmp -Force
$exe = Join-Path $tmp "$Binary.exe"
if (-not (Test-Path $exe)) { throw "archive did not contain $Binary.exe" }
Copy-Item -Path $exe -Destination (Join-Path $InstallDir "$Binary.exe") -Force
Info "installed $InstallDir\$Binary.exe"

# add to user PATH if missing
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
if (($userPath -split ';') -notcontains $InstallDir) {
[Environment]::SetEnvironmentVariable('Path', "$userPath;$InstallDir", 'User')
$env:Path = "$env:Path;$InstallDir"
Info "added $InstallDir to your user PATH (restart your shell to pick it up)"
}

# --- prove it works -----------------------------------------------------
$bin = Join-Path $InstallDir "$Binary.exe"
Write-Host ''
& $bin doctor
Write-Host ''
& $bin demo repository-policy
Write-Host ''
Info "done — author your own policy with '$Binary init'"
}
finally {
Remove-Item -Path $tmp -Recurse -Force -ErrorAction SilentlyContinue
& (Join-Path $dir "$binary.exe") doctor
Write-Host " done. run '$binary --help' to get started."
}
finally { Remove-Item -Recurse -Force $tmp }
Loading
Loading