POST /v1/identity/verify: an AERE Identity presentation judged by the published command line -> VALID / PARTIAL / INVALID with every row, the claims shown and the subject when no row failed, and the command that reproduces the verdict. POST /v1/compliance/check: your policy judged on a presentation -> COMPLIANT / NOT_COMPLIANT with the reasons and, with record, the decision as an AIP-23 envelope without personal data. In Go the presentation, keys, lists and policy travel as json.RawMessage: a map or float64 would change numbers above 2^53 and the canonical text the signatures cover. The .NET negative control now builds clean for each planted defect (an incremental build could run the tests against the previous planted library). A negative control for the JavaScript and Python routes is added. Tests: JavaScript 13, Python 14, Go ok, Java 10/10 (and the Java 8 API gate); negative controls Go 9/9, Java 10/10, .NET 12/12, JavaScript and Python 4/4.
62 lines
6.1 KiB
Bash
62 lines
6.1 KiB
Bash
#!/bin/bash
|
|
# control-negativ.sh - IN WSL: controlul negativ al probelor clientului .NET (Aere.Cloud). Fiecare paznic se strica intr-o COPIE a sursei
|
|
# (depozitul nu se atinge), probele ruleaza pe copie si proba tinta TREBUIE sa pice. O plantare a carei ancora nu apare exact o data, sau
|
|
# care nu compileaza (TreatWarningsAsErrors), e STRICAT, nu rosu. La urma, sursa neatinsa trebuie sa treaca intreaga.
|
|
# bash csharp/control-negativ.sh (Linux sau WSL, cu un SDK .NET 8+ in PATH; `dotnet` gasit altundeva: DOTNET_ROOT + PATH)
|
|
# 2026-09-29: caile sunt derivate (dosarul scriptului, un dosar temporar), nu scrise fix, ca scriptul sa mearga si din depozitul public.
|
|
set -u
|
|
export DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1
|
|
command -v dotnet >/dev/null || { echo "STRICAT: dotnet nu e in PATH"; exit 2; }
|
|
S=$(cd "$(dirname "$0")" && pwd)
|
|
W=$(mktemp -d "${TMPDIR:-/tmp}/sdk-csharp-control-XXXX")
|
|
cp -r "$S/Aere.Cloud" "$S/Aere.Cloud.Tests" "$W/"; rm -rf "$W"/*/bin "$W"/*/obj
|
|
SRC="$W/Aere.Cloud/AereCloudClient.cs"; tr -d '\r' < "$S/Aere.Cloud/AereCloudClient.cs" > "$W/original.cs"
|
|
cat > "$W/plantari.py" <<'PY'
|
|
import sys
|
|
P = [
|
|
("exportul jsonl declarat verificat fara hash", 'format == "jsonl" ? !string.IsNullOrEmpty(digest) && digest == Sha256Hex(r.Body) : null', 'format == "jsonl" ? true : null', "ExportulZilei"),
|
|
("ziua tinuta acceptata fara comparatie", 'new KeptCheck(day, "held", held, local, local == held, null)', 'new KeptCheck(day, "held", held, local, true, null)', "ExportulPastrat"),
|
|
("piatra zilei sterse acceptata fara comparatie", 'new KeptCheck(day, "expired", digest, local, local == digest, del)', 'new KeptCheck(day, "expired", digest, local, true, del)', "ExportulPastrat"),
|
|
# inaintea throw-ului pentru non-2xx (prima forma a plantarii statea dupa el, deci nu se executa niciodata si "a ramas verde")
|
|
("un 429 intors ca nepotrivire", ' if (r.Status < 200 || r.Status >= 300) throw new AereCloudException(r.Status, Encoding.UTF8.GetString(r.Body), "/account/audit");\n var held', ' if (r.Status == 429) return new KeptCheck(day, "held", "", local, false, null);\n if (r.Status < 200 || r.Status >= 300) throw new AereCloudException(r.Status, Encoding.UTF8.GetString(r.Body), "/account/audit");\n var held', "ExportulPastrat"),
|
|
("cheia trimisa si fara attest", 'return JsonAsync(HttpMethod.Post, "/pq/readiness", b, attest, ct);', 'return JsonAsync(HttpMethod.Post, "/pq/readiness", b, true, ct);', "ReadinessCheiaNumaiLaAttest"),
|
|
("redirectarile urmate (cheia ar pleca spre alta gazda)", 'new HttpClientHandler { AllowAutoRedirect = false }', 'new HttpClientHandler { AllowAutoRedirect = true }', "RedirectareaNuEUrmata"),
|
|
("webhook acceptat fara semnatura", 'return CryptographicOperations.FixedTimeEquals(want, got);', 'return got.Length >= 0 || CryptographicOperations.FixedTimeEquals(want, got);', "VerifyWebhook"),
|
|
("cheia goala acceptata", 'if (string.IsNullOrEmpty(apiKey)) throw', 'if (apiKey == "niciodata-" + "asa") throw', "CheiaEObligatorie"),
|
|
("lantul cerut scapat din Trust API", '(chain > 0 ? "?chain=" + chain : "")', '(chain > 0 ? "" : "")', "TrustApiVerify"),
|
|
("conformitatea pe ruta identitatii (1.7.0)", 'JsonAsync(HttpMethod.Post, "/compliance/check", request, true, ct);', 'JsonAsync(HttpMethod.Post, "/identity/verify", request, true, ct);', "IdentityCompliance"),
|
|
("identitatea fara cheie (1.7.0)", 'JsonAsync(HttpMethod.Post, "/identity/verify", request, true, ct);', 'JsonAsync(HttpMethod.Post, "/identity/verify", request, false, ct);', "IdentityCompliance"),
|
|
("un rezultat RPC fara forma citit ca zero", ' throw new AereCloudException(200, e.GetRawText(), "/rpc");', ' return 0;', "EroriSiBlockNumber"),
|
|
]
|
|
if sys.argv[1] == "n": print(len(P)); sys.exit(0)
|
|
i = int(sys.argv[1]); nume, vechi, nou, tinta = P[i]
|
|
t = open(sys.argv[2]).read()
|
|
if t.count(vechi) != 1: print("ANCORA %d" % t.count(vechi)); sys.exit(3)
|
|
open(sys.argv[3], "w").write(t.replace(vechi, nou)); print(nume + "|" + tinta)
|
|
PY
|
|
ruleaza() { # -> iesirea probelor in $W/iesire.txt; cod: 0 rulat, 2 nu compileaza
|
|
# 2026-09-30: constructie CURATA la fiecare plantare. Cu constructia incrementala, "cheia goala acceptata" a iesit de doua ori din trei
|
|
# CONTROL CAZUT: probele rulau cu biblioteca plantarii de DINAINTE (copiata sau nu in bin-ul probelor dupa marcile de timp), deci
|
|
# masurau alta plantare decat cea numita. Fara bin/ si obj/ nu ramane nimic de la rularea anterioara.
|
|
rm -rf "$W"/Aere.Cloud/bin "$W"/Aere.Cloud/obj "$W"/Aere.Cloud.Tests/bin "$W"/Aere.Cloud.Tests/obj
|
|
( cd "$W" && dotnet build Aere.Cloud.Tests -c Release -p:NuGetAudit=false -nodeReuse:false -p:UseSharedCompilation=false > build.log 2>&1 < /dev/null ) || return 2
|
|
# exact UN dll de probe in iesirea acestei constructii (un `| head -1` peste mai multe ar alege la intamplare)
|
|
local dll; dll=$(ls "$W"/Aere.Cloud.Tests/bin/Release/net*/Aere.Cloud.Tests.dll 2>/dev/null); [ "$(printf '%s\n' "$dll" | grep -c .)" = 1 ] || return 2
|
|
dotnet "$dll" > "$W/iesire.txt" 2>&1 < /dev/null; return 0
|
|
}
|
|
N=$(python3 "$W/plantari.py" n); RAU=0
|
|
for i in $(seq 0 $((N - 1))); do
|
|
L=$(python3 "$W/plantari.py" "$i" "$W/original.cs" "$SRC"); c=$?
|
|
[ "$c" = 0 ] || { echo " STRICAT plantarea $i: $L"; RAU=$((RAU+1)); continue; }
|
|
nume=${L%|*}; tinta=${L#*|}
|
|
if ! ruleaza; then echo " STRICAT $nume: nu compileaza ($(grep -m1 -oE 'error [A-Z]+[0-9]+[^[]*' "$W/build.log"))"; RAU=$((RAU+1)); continue; fi
|
|
if grep -q "^--- FAIL: $tinta" "$W/iesire.txt"; then echo " ROSU cum trebuia $nume (pica $(grep -c '^--- FAIL' "$W/iesire.txt"): $(grep '^--- FAIL' "$W/iesire.txt" | cut -d: -f2 | tr '\n' ' '))"
|
|
else echo " CONTROL CAZUT $nume: $tinta a ramas verde"; RAU=$((RAU+1)); fi
|
|
done
|
|
cp "$W/original.cs" "$SRC"
|
|
if ruleaza && ! grep -q '^--- FAIL' "$W/iesire.txt" && grep -q '^--- PASS' "$W/iesire.txt"; then echo " martor: sursa neatinsa, $(grep -c '^--- PASS' "$W/iesire.txt") probe verzi"
|
|
else echo " MARTORUL nu e verde"; RAU=$((RAU+1)); fi
|
|
[ "$RAU" = 0 ] && echo "CONTROL NEGATIV TRECUT ($N din $N rosii, martorul verde)" || echo "CONTROL NEGATIV: $RAU probleme"
|
|
rm -rf "$W"
|
|
exit $([ "$RAU" = 0 ] && echo 0 || echo 1)
|