Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,6 @@ export async function POST(
if (!entry.manifest.compatibility.providers.includes('github')) {
return NextResponse.json({ error: 'Action does not support GitHub' }, { status: 400 });
}
if (requiresWorkflowWrite(entry.manifest.files) && !hasWorkflowWrite(auth.installation.permissions)) {
return NextResponse.json(
{
error:
'GitHub App needs Workflows: write permission to install actions into .github/workflows. Update the sh1pt GitHub App permissions, accept the installation update in GitHub, then retry.',
},
{ status: 403 },
);
}

let render;
try {
Expand All @@ -102,6 +93,24 @@ export async function POST(
if (!token.ok || !token.data) {
return NextResponse.json({ error: token.error ?? 'Could not mint installation token' }, { status: token.status || 500 });
}
if (token.data.permissions) {
await admin
.from('github_installations')
.update({ permissions: token.data.permissions, updated_at: new Date().toISOString() })
.eq('id', auth.installation.id);
}
Comment on lines +96 to +101
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Supabase update error silently swallowed

The update() call's result is awaited but never destructured for { error }. If the row update fails (network hiccup, RLS policy, wrong primary key type), the failure is invisible — no log, no side-effect on the current request. The PR explicitly lists "refresh stored installation permissions from the token response" as a goal, so a silent failure here defeats that goal without any signal for debugging.

Fix in Codex Fix in Claude Code

if (
requiresWorkflowWrite(entry.manifest.files) &&
!hasFreshWorkflowWrite(token.data.permissions, auth.installation.permissions)
) {
return NextResponse.json(
{
error:
'GitHub App needs Workflows: write permission to install actions into .github/workflows. Update the sh1pt GitHub App permissions, accept the installation update in GitHub, then retry.',
},
{ status: 403 },
);
}
Comment on lines 78 to +113
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 renderPack and token minting now precede the permission guard

In the previous code, a missing workflow:write permission produced an early 403 before renderPack or mintInstallationToken were called. Now both are invoked unconditionally, so a denied request burns a GitHub API token-mint call and runs the pack renderer for nothing. For actions that write to .github/workflows/ and are frequently attempted before the org accepts the new permission, this adds avoidable latency and GitHub API quota consumption on each retry.

Fix in Codex Fix in Claude Code


const outcome = await openPackPullRequest({
client: { token: token.data.token },
Expand Down Expand Up @@ -145,6 +154,14 @@ function hasWorkflowWrite(permissions: Record<string, string> | null | undefined
return permissions?.workflows === 'write';
}

function hasFreshWorkflowWrite(
tokenPermissions: Record<string, string> | null | undefined,
storedPermissions: Record<string, string> | null | undefined,
): boolean {
if (tokenPermissions) return hasWorkflowWrite(tokenPermissions);
return hasWorkflowWrite(storedPermissions);
}

function normalizeInputs(value: unknown): { ok: true; value: RenderInputs } | { ok: false; error: string } {
if (value === undefined) return { ok: true, value: {} };
if (!value || typeof value !== 'object' || Array.isArray(value)) {
Expand Down
Loading