#!/usr/bin/env nu
use common.nu *
def test-repos-pagination [url: string] {
print "verifying /repos pagination..."
print " testing limit=1..."
let items = (http get $"($url)/repos?limit=1" | from json -o)
if ($items | length) != 1 {
fail "expected 1 item with limit=1"
}
print $" count: ($items | length)"
let all_items = (http get $"($url)/repos" | from json -o)
print $" count: ($all_items | length)"
if ($all_items | length) > 1 {
let first_did = ($all_items | get 0).did
print $" testing cursor with did ($first_did)..."
let cursor_items = (http get $"($url)/repos?cursor=($first_did)&limit=1" | from json -o)
if ($cursor_items | length) > 0 {
let next_did = ($cursor_items | get 0).did
if $first_did == $next_did {
fail "cursor did should be excluded from results"
}
print $" next did: ($next_did)"
}
}
print "/repos pagination passed!"
}
def test-repos-validation-errors [url: string] {
print "verifying /repos error handling..."
print " testing PUT /repos with invalid DID..."
http put -f -e -t application/json $"($url)/repos" [{ did: "invalid" }]
| assert-status 400 "PUT /repos invalid DID"
print " testing DELETE /repos with invalid DID..."
http delete -f -e -t application/json $"($url)/repos" --data [{ did: "invalid" }]
| assert-status 400 "DELETE /repos invalid DID"
print " testing GET /repos with invalid cursor..."
http get -f -e $"($url)/repos?cursor=invalid"
| assert-status 400 "GET /repos invalid cursor"
print "/repos validation errors passed!"
}
def test-body-deletion-routes [url: string, did: string] {
print "verifying operator erasure routes (/redactions)..."
http post -f -e -H [Content-Length 0] $"($url)/redactions/not-a-did" ""
| assert-status 400 "redaction rejects invalid target"
http post -f -e -H [Content-Length 0] $"($url)/redactions/at://($did)/app.bsky.feed.post/3kzbif5moe22m?target=nope" ""
| assert-status 400 "record redaction rejects invalid target query param"
let record_report = (http post -H [Content-Length 0] $"($url)/redactions/at://($did)/app.bsky.feed.post/3kzbif5moe22m" "")
if $record_report.heads_redacted != 0 or $record_report.history_redacted != 0 {
fail "empty record redaction should be idempotent"
}
http post -f -e -H [Content-Length 0] $"($url)/redactions/($did)?target=head" ""
| assert-status 400 "repo erase rejects a body target"
let repo_report = (http post -H [Content-Length 0] $"($url)/redactions/($did)" "")
if $repo_report.heads_redacted != 0 or $repo_report.history_redacted != 0 {
fail "empty repo erase should be idempotent"
}
http get -f -e $"($url)/repos/($did)"
| assert-status 404 "an erased repo should be forgotten"
print "verifying /repos untrack routes..."
http put -t application/json $"($url)/repos" [{did: $did}]
let untrack_resp = (http delete $"($url)/repos/($did)")
if ($untrack_resp | is-empty) {
# untrack returns array/ndjson of untracked DIDs
}
let info = (http get $"($url)/repos/($did)")
if $info.tracked {
fail "untrack should set tracked=false"
}
print "operator erasure and untrack routes passed!"
}
def main [] {
let port = resolve-test-port 3001
let url = $"http://localhost:($port)"
let db_path = (mktemp -d -t hydrant_repos_api.XXXXXX)
print $"starting hydrant for /repos API verification..."
let binary = build-hydrant
let instance = (with-env { HYDRANT_MODE: "filter" } {
start-hydrant $binary $db_path $port
})
if not (wait-for-api $url) {
fail "hydrant did not start" $instance.pid
}
let dids = [
"did:plc:dfl62fgb7wtjj3fcbb72naae"
"did:plc:q6gjnv26m4ay3m42ojvzx2m4"
]
http put -t application/json $"($url)/repos" ($dids | each { |d| { did: $d } })
test-repos-pagination $url
test-repos-validation-errors $url
test-body-deletion-routes $url ($dids | first)
kill $instance.pid
}