Skip to content

store: honor snap confinement on install - #133

Merged
fwerkor merged 6 commits into
mainfrom
fix/snap-install-confinement
Aug 20, 2026
Merged

fwerkor merged 6 commits into
mainfrom
fix/snap-install-confinement

Conversation

@fwerkor

@fwerkor fwerkor commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • include confinement in Canonical catalog metadata and invalidate the old catalog snapshot
  • generate --classic / --devmode install commands when required
  • pass confinement through WebDesktop and translate it to snapd REST install flags

Tests

  • npm run build
  • npm run test:worker
  • install command assertions for strict/classic/devmode
  • node --check package/capos/capos-webdesktop/htdocs/assets/app.js
  • compile smoke for package/capos/capos-webdesktop/src/api.cpp

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 20, 2026 •

Copy link
Copy Markdown

Deploying capos with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3775c1b
Status: ✅  Deploy successful!
Preview URL: https://dd6df613.capos.pages.dev
Branch Preview URL: https://fix-snap-install-confinement.capos.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 20, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
capos-snap fa663b3 Aug 20 2026, 07:58 AM

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3a733b4f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread website/snap/worker/index.ts
Comment thread website/snap/worker/index.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11d006e561

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread website/snap/src/App.tsx
@fwerkor
fwerkor enabled auto-merge August 20, 2026 07:50
@fwerkor
fwerkor merged commit e74f25e into main Aug 20, 2026
10 checks passed
@fwerkor
fwerkor deleted the fix/snap-install-confinement branch August 20, 2026 08:01
@fwerkor fwerkor self-assigned this Aug 20, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa663b323f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const channelMap = Array.isArray(payload['channel-map']) ? payload['channel-map'] : [];
const preferred = channelMap.find((entry:any) => entry.channel?.architecture === 'amd64' && entry.channel?.risk === 'stable') || channelMap[0] || {};
const confinementByArchitecture = Object.fromEntries(channelMap
.filter((entry:any) => entry.channel?.name === 'stable' && ['strict','classic','devmode'].includes(entry.confinement))

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 Badge Match Canonical's full stable channel name

Canonical's v2 info response identifies stable channels with full names such as latest/stable (and risk: "stable"), rather than name: "stable", so this filter normally produces an empty confinement map. Because {} passes the UI's metadata-loaded check, copied commands then fall back to the amd64 app.confinement and can still use the wrong flag on another architecture. Fresh evidence against the resolved thread is that the new test fixture shortens these names to stable, masking the production response shape; select the default track's stable entry and reject an empty map instead.

Useful? React with 👍 / 👎.

function validSnapName(name){return typeof name==="string"&&name.length<=64&&/^(?=.*[a-z])[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(name);}
async function installFromStore(name,channel){if(!state.session?.is_sudo)throw new Error("安装 Snap 需要 sudo 权限");if(state.installed.some(s=>s.name===name)){postStoreState();return}if(state.installing.has(name))return;state.installing.set(name,1);postStore({type:"capos-webdesktop:progress",version:1,name,progress:1});try{const body=new URLSearchParams({channel:channel||"stable"}).toString();await snapAction(name,"install",`安装 ${name}`,body,progress=>{state.installing.set(name,progress);postStore({type:"capos-webdesktop:progress",version:1,name,progress});});state.installing.delete(name);postStoreState();}catch(error){state.installing.delete(name);postStoreState();const message=error instanceof Error?error.message:String(error);postStore({type:"capos-webdesktop:error",version:1,name,message});toast(message,true);}}
function installConfinement(value){return value==="classic"||value==="devmode"||value==="strict"?value:"";}
async function storeConfinement(name,channel){const data=await request(`/snapd/find?name=${encodeURIComponent(name)}`);const snaps=Array.isArray(snapResult(data))?snapResult(data):[];const snap=snaps.find(item=>item?.name===name);if(!snap)throw new Error(`无法解析 ${name} 的安装元数据`);const requested=channel||"stable";const channels=snap.channels&&typeof snap.channels==="object"?Object.entries(snap.channels):[];const match=channels.find(([key,info])=>key===requested||key.endsWith(`/${requested}`)||info?.channel===requested);const mode=installConfinement(match?.[1]?.confinement||snap.confinement);if(!mode)throw new Error(`无法确定 ${name} 的 confinement`);return mode;}

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 Badge Resolve the exact track before choosing confinement

When a snap exposes multiple tracks with a channel at the requested risk, a bare request such as stable makes this suffix match select whichever */stable entry happens to appear first, while the subsequent install still sends the bare channel for snapd to resolve against its default track. If those tracks use different confinement modes, WebDesktop supplies the flag for one track while installing another and the operation fails. Fresh evidence beyond the resolved architecture report is this newly added ambiguous multi-track lookup; resolve the default track first or require an exact full-channel match.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant