mirror your GitHub repos to tangled.org automatically
1

Configure Feed

Select the types of activity you want to include in your feed.

fix: tidy up scopes

+27 -3
+1 -1
server/api/atproto/login.get.ts
··· 20 20 // so this is safe to use as an opaque link key. 21 21 const url = await client.authorize(handle, { 22 22 state: installationId, 23 - scope: 'atproto transition:generic', 23 + scope: SYNCHUB_OAUTH_SCOPE, 24 24 }) 25 25 26 26 await sendRedirect(event, url.toString(), 302)
+26 -2
server/utils/atproto-oauth.ts
··· 12 12 import { useDb } from './db' 13 13 import { decrypt, encrypt } from './encryption' 14 14 15 + /** 16 + * Granular permissions per https://atproto.com/specs/permission. 17 + * 18 + * - `atproto`: required by the OAuth profile. 19 + * - `repo:sh.tangled.publicKey`: write the user's tangled SSH public key 20 + * records (publish on connect, rotate from the dashboard). 21 + * - `repo:sh.tangled.repo`: write `sh.tangled.repo` records (initial repo 22 + * enrolment, plus future description / topic updates). 23 + * - `rpc:sh.tangled.repo.create?aud=*`: call the `sh.tangled.repo.create` 24 + * procedure on any knot, and by extension mint the matching service-auth 25 + * JWT via the PDS. We use `aud=*` rather than pinning a specific knot 26 + * because (a) the granular-scope spec requires `aud` to be either a 27 + * fragmented `did:web:host#service` or `*`, but tangled knots accept 28 + * plain `did:web:host` audiences on issued JWTs, and (b) it's 29 + * forward-compatible with per-user knots (PLAN.md open question 1). 30 + * Still narrowly scoped — only one specific procedure NSID. 31 + */ 32 + export const SYNCHUB_OAUTH_SCOPE = [ 33 + 'atproto', 34 + 'repo:sh.tangled.publicKey', 35 + 'repo:sh.tangled.repo', 36 + 'rpc:sh.tangled.repo.create?aud=*', 37 + ].join(' ') 38 + 15 39 let cachedClient: NodeOAuthClient | undefined 16 40 17 41 /** ··· 42 66 const isLoopback = publicURL.startsWith('http://127.0.0.1') || publicURL.startsWith('http://localhost') 43 67 const clientId = isLoopback 44 68 // Loopback dev: spec-defined synthetic client_id; no metadata fetched by PDS. 45 - ? `http://localhost?redirect_uri=${encodeURIComponent(`${publicURL}/api/atproto/callback`)}&scope=${encodeURIComponent('atproto transition:generic')}` 69 + ? `http://localhost?redirect_uri=${encodeURIComponent(`${publicURL}/api/atproto/callback`)}&scope=${encodeURIComponent(SYNCHUB_OAUTH_SCOPE)}` 46 70 : `${publicURL}/.well-known/atproto-client-metadata.json` 47 71 48 72 const options: NodeOAuthClientOptions = { ··· 53 77 redirect_uris: [`${publicURL}/api/atproto/callback`], 54 78 grant_types: ['authorization_code', 'refresh_token'], 55 79 response_types: ['code'], 56 - scope: 'atproto transition:generic', 80 + scope: SYNCHUB_OAUTH_SCOPE, 57 81 application_type: 'web', 58 82 token_endpoint_auth_method: 'private_key_jwt', 59 83 token_endpoint_auth_signing_alg: 'ES256',