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
2 changes: 2 additions & 0 deletions .agents/skills/validate-sas-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ When the owner explicitly authorizes a model migration, retain failed histories

Publication plans must reject empty/no-op targets and stale source/archive/run bindings. Native SQL is not an authenticated administrator session: use the existing admin review flow for publication, preserving `enforce_admin_only_publish` and the adversarial trigger. Do not forge claims or alter roles/triggers to publish. Verify actual public versions and model/protocol scope afterward.

The admin review write must retain the verified administrator's authenticated client, pin the evaluated version and confirm the returned row's status, publication flag and reviewer. A closed dialog or successful HTTP transport alone is not publication evidence. Run the real Supabase HTTP transport regressions in `tests/admin-review-update.test.ts`; database denials, missing rows and mismatched versions/actors must reject. Confirm the actual persisted/public subset afterward.

The original business case contract is pinned in `scripts/adversarial-approval.mjs`. Qualification, registry recording and publication planning require all 21 skills and 273 unchanged cases, including inputs, contexts, severities and expectations. Pilots never qualify. Test changes are not an allowed failure fix. Review each distinct raw response against the original domain expectation and record hash-bound decisions; group identical baseline evidence with the existing review-group command without automatically generating verdicts.

For interrupted local inference, reuse the worker's explicit `--resume` only when it accepts the original incomplete JSONL prefix and exact plan/runtime/package fingerprints. Preserve all prior rows, including errors. The worker requires a hash-bound attempt journal ending at a completed case, appends only not-yet-started cases and records its actual resumption. An in-flight or unknown attempt blocks recovery. Use `--max-cases N` for an explicit boundary checkpoint; exit 4 remains incomplete evidence. Changed or legacy runtime evidence must remain separate; never edit a raw output or its plan hash to make recovery pass. Run the deterministic recovery regressions with `python3 tests/worker_resume_test.py`.
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ Component artifacts are versioned and released independently via git tags:
- **`super-agent` CLI** — `cli-v*` tags publish cross-platform binaries.
- **`@superagentskill/sdk`** — versioned in `packages/sdk-ts/package.json`.

## [0.6.5] — 2026-10-24 — *Genesis* (alpha) — Authenticated publication repair

### Changed

- Preserve the verified administrator session through RLS and publication triggers.
- Bind approval writes to the evaluated version and confirm the returned reviewer/status; reject errors and no-op writes.
- Keep failed server responses from being reported as successful review decisions.

## [0.6.4] — 2026-10-23 — *Genesis* (alpha) — Maintenance release

### Changed
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tanstack_start_ts",
"version": "0.6.4",
"version": "0.6.5",
"private": true,
"sideEffects": false,
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "superagentskill",
"version": "0.6.4",
"version": "0.6.5",
"description": "Agent skills and candidate workflows from Super Agent Skill. Published registry packages expose available trust and execution evidence; candidate workflows include offline fixtures.",
"author": {
"name": "Super Agent Skill",
Expand Down
42 changes: 42 additions & 0 deletions src/lib/admin/review-update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { AppDatabaseClient } from "@/integrations/supabase/database";

export type ReviewStatus = "draft" | "pending" | "approved" | "paused" | "rejected";

/** Keep the verified administrator's JWT so RLS and publication triggers see the real actor. */
export async function persistReviewDecision(
client: AppDatabaseClient,
input: {
slug: string;
status: ReviewStatus;
userId: string;
version?: string;
notes: string | null;
},
) {
const published = input.status === "approved";
let query = client
.from("packages")
.update({
review_status: input.status,
review_notes: input.notes,
reviewed_by: input.userId,
reviewed_at: new Date().toISOString(),
is_published: published,
})
.eq("slug", input.slug);
if (input.version) query = query.eq("latest_version", input.version);
const { data, error } = await query
.select("slug,latest_version,review_status,is_published,reviewed_by")
.single();
if (error) throw new Error(`Review was not saved: ${error.message}`);
if (
!data ||
data.slug !== input.slug ||
data.review_status !== input.status ||
data.is_published !== published ||
data.reviewed_by !== input.userId ||
(input.version && data.latest_version !== input.version)
)
throw new Error("Review was not saved with the expected version, status and administrator");
return { ok: true as const, status: input.status, is_published: published };
}
34 changes: 13 additions & 21 deletions src/lib/admin/review.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import type { AppDatabaseClient } from "@/integrations/supabase/database";
import { createServerFn } from "@tanstack/react-start";
import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware";
import { supabaseAdmin as _supabaseAdmin } from "@/integrations/supabase/client.server";
import { persistReviewDecision, type ReviewStatus } from "./review-update";
export type { ReviewStatus } from "./review-update";
const supabaseAdmin = _supabaseAdmin;

export type ReviewStatus = "draft" | "pending" | "approved" | "paused" | "rejected";

export type ReviewQueueItem = {
id: string;
slug: string;
Expand Down Expand Up @@ -116,7 +116,7 @@ export const setReviewStatus = createServerFn({ method: "POST" })
})
.handler(async ({ context, data }) => {
await assertAdmin(context.supabase, context.userId);
const isPublished = data.status === "approved";
let approvedVersion: string | undefined;

// Mandatory adversarial gate: a package can only be approved (and thus
// become publicly installable / served via MCP) if the CURRENT version
Expand All @@ -126,33 +126,25 @@ export const setReviewStatus = createServerFn({ method: "POST" })
if (data.status === "approved") {
const gate = await assertAdversarialGate(data.slug);
if (!gate.ok) {
throw new Response(
JSON.stringify({ error: "adversarial_gate_failed", reason: gate.reason, run: gate.run }),
{ status: 422, headers: { "Content-Type": "application/json" } },
);
throw new Error(`Adversarial approval gate failed: ${gate.reason}`);
}
approvedVersion = gate.version;
}

const { error } = await supabaseAdmin
.from("packages")
.update({
review_status: data.status,
review_notes: data.notes,
reviewed_by: context.userId,
reviewed_at: new Date().toISOString(),
is_published: isPublished,
})
.eq("slug", data.slug);
if (error) throw new Response(error.message, { status: 500 });
return { ok: true, status: data.status, is_published: isPublished };
return persistReviewDecision(context.supabase, {
...data,
userId: context.userId,
version: approvedVersion,
});
});

// Approval thresholds. Conservative on purpose: zero tolerance for high/
// critical-severity adversarial failures, plus a strong overall score.
const MIN_SEVERITY_WEIGHTED_SCORE = 0.9;
const MIN_PASS_RATE = 0.9;

type GateResult = { ok: true; run: unknown } | { ok: false; reason: string; run: unknown };
type GateResult =
{ ok: true; run: unknown; version: string } | { ok: false; reason: string; run: unknown };

async function assertAdversarialGate(slug: string): Promise<GateResult> {
const { data: pkg } = await supabaseAdmin
Expand Down Expand Up @@ -224,5 +216,5 @@ async function assertAdversarialGate(slug: string): Promise<GateResult> {
run,
};
}
return { ok: true, run };
return { ok: true, run, version: ver.version };
}
14 changes: 12 additions & 2 deletions src/lib/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
* We are still pre-1.0: rapid evolution, no stability guarantees.
*/

export const PLATFORM_VERSION = "0.6.4" as const;
export const PLATFORM_VERSION = "0.6.5" as const;
export const PLATFORM_CODENAME = "Genesis" as const;
export const PLATFORM_STAGE: "alpha" | "beta" | "ga" = "alpha";
export const PLATFORM_BUILD_DATE = "2026-10-23" as const;
export const PLATFORM_BUILD_DATE = "2026-10-24" as const;

export type ChangelogEntry = {
version: string;
Expand All @@ -30,6 +30,16 @@ export type ChangelogEntry = {
* Every deployed change appends a new entry (or amends the top one before shipping).
*/
export const CHANGELOG: ChangelogEntry[] = [
{
version: "0.6.5",
date: "2026-10-24",
kind: "patch",
title: "Authenticated publication repair",
highlights: [
"Preserve the administrator session through RLS and publication triggers.",
"Confirm the saved version, reviewer and publication state before reporting success.",
],
},
{
version: "0.6.4",
date: "2026-10-23",
Expand Down
4 changes: 4 additions & 0 deletions src/routes/admin.review.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ function ReviewRow({ item, onAction }: { item: ReviewQueueItem; onAction: () =>
mutationFn: (input: { status: ReviewStatus; notes: string | null }) =>
setStatusFn({ data: { slug: item.slug, status: input.status, notes: input.notes } }),
onSuccess: (res) => {
if (res?.ok !== true) {
toast.error("Review was not confirmed. Refresh the queue and verify its status.");
return;
}
toast.success(`Marked as ${res.status}${res.is_published ? " · live" : ""}`);
setOpen(null);
setNotes("");
Expand Down
86 changes: 86 additions & 0 deletions tests/admin-review-update.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import test from "node:test";
import assert from "node:assert/strict";
import { createClient } from "@supabase/supabase-js";
import type { Database } from "../src/integrations/supabase/database.ts";
import { persistReviewDecision } from "../src/lib/admin/review-update.ts";

const input = {
slug: "review-fixture",
status: "approved" as const,
userId: "00000000-0000-4000-8000-000000000001",
version: "0.1.4",
notes: "Offline transport regression only",
};
const saved = {
slug: input.slug,
latest_version: input.version,
review_status: "approved",
is_published: true,
reviewed_by: input.userId,
};
function client(response: unknown, status = 200, inspect?: (url: URL, init: RequestInit) => void) {
return createClient<Database>("https://review-fixture.invalid", "test-publishable-key", {
auth: { persistSession: false, autoRefreshToken: false },
global: {
headers: { Authorization: "Bearer synthetic-admin-session" },
fetch: async (url, init) => {
inspect?.(new URL(String(url)), init ?? {});
return new Response(JSON.stringify(response), {
status,
headers: { "content-type": "application/json" },
});
},
},
});
}

test("review persistence sends the caller JWT and guards the evaluated version", async () => {
let writes = 0;
const db = client(saved, 200, (url, init) => {
writes++;
assert.equal(init.method, "PATCH");
assert.equal(new Headers(init.headers).get("authorization"), "Bearer synthetic-admin-session");
assert.equal(url.searchParams.get("slug"), "eq.review-fixture");
assert.equal(url.searchParams.get("latest_version"), "eq.0.1.4");
const body = JSON.parse(String(init.body));
assert.equal(body.reviewed_by, input.userId);
assert.equal(body.is_published, true);
});
assert.deepEqual(await persistReviewDecision(db, input), {
ok: true,
status: "approved",
is_published: true,
});
assert.equal(writes, 1);
});

test("a publication trigger/RLS denial rejects instead of reporting approval", async () => {
await assert.rejects(
persistReviewDecision(
client({ code: "42501", message: "marketplace_publish_forbidden" }, 403),
input,
),
/Review was not saved: marketplace_publish_forbidden/,
);
});

test("no updated row cannot become a successful review", async () => {
await assert.rejects(
persistReviewDecision(client({ code: "PGRST116", message: "No matching version" }, 406), input),
/Review was not saved: No matching version/,
);
});

test("a mismatched persisted version, actor or publication flag rejects", async () => {
for (const change of [
{ latest_version: "0.1.5" },
{ reviewed_by: null },
{ is_published: false },
{ review_status: "draft" },
]) {
await assert.rejects(
persistReviewDecision(client({ ...saved, ...change }), input),
/expected version, status and administrator/,
);
}
});
Loading