Resolve a named repository owner server-side, and prove a board refuses a stranger
Two changes that both remove a guess.
`POST /api/v1/user/repos` and `POST /api/v1/orgs/{org}/repos` make the
caller pick a route by the kind of owner, and a client handed `OWNER/NAME`
knows only that an owner was named. Both CLIs read a slash as proof the
owner was an organization, so `repo create AtlantisPleb/thing` asked the
organization route to create under a person. `POST /api/v1/repos` takes
`owner` as a field and resolves the kind here, so no client has to guess.
Omitting `owner` means the caller's own namespace. The two GitHub-shaped
routes stay as they were.
The caller's own login resolves without asking GitHub, because the token
already authenticates that identity. Another person's namespace is refused
outright rather than asked about: GitHub cannot answer "is this login an
organization you administer" for a login that is a person, and the answer
it gives instead is a worse error than the true one.
The project lifecycle routes already carried the writable-membership
check, but every test of them ran against a private repository, where a
404 comes from visibility before write authority is ever consulted. A
delete route with no authorization check at all would have passed that
suite. The new test uses a public repository: the outsider reads the board
first, so the refusal that follows can only be about writing, and the
board is listed before and after so a refusal that quietly went through
would still fail. Removing `writable_repository!` from `update/2` and
`delete/2` fails it, which is the point.
Resolve a named repository owner server-side, and prove a board refuses a stranger
Deploy story
What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.
- pushed
- by user · WAL seq 442 · 2026-08-26T08:33:57.055766Z
Changed files
-
modified
lib/openagents/repositories.ex -
modified
lib/openagents/repositories/github_projection.ex -
modified
lib/openagents_web/api_route_authority.ex -
modified
lib/openagents_web/controllers/repository_controller.ex -
modified
lib/openagents_web/router.ex -
modified
priv/api-contracts/repositories-v1.json -
modified
priv/docs/rest-api.md -
modified
test/openagents_web/controllers/project_controller_test.exs -
modified
test/openagents_web/controllers/repository_controller_test.exs
Diff
9 files changed, +255 -0
lib/openagents/repositories.ex modified +41
@@ -248,6 +248,47 @@ defmodule OpenAgents.Repositories do
| 248 | 248 |
|
| 249 | 249 |
|
| 250 | 250 |
|
| 251 |
|
|
| 252 |
|
|
| 253 |
|
|
| 254 |
|
|
| 255 |
|
|
| 256 |
|
|
| 257 |
|
|
| 258 |
|
|
| 259 |
|
|
| 260 |
|
|
| 261 |
|
|
| 262 |
|
|
| 263 |
|
|
| 264 |
|
|
| 265 |
|
|
| 266 |
|
|
| 267 |
|
|
| 268 |
|
|
| 269 |
|
|
| 270 |
|
|
| 271 |
|
|
| 272 |
|
|
| 273 |
|
|
| 274 |
|
|
| 275 |
|
|
| 276 |
|
|
| 277 |
|
|
| 278 |
|
|
| 279 |
|
|
| 280 |
|
|
| 281 |
|
|
| 282 |
|
|
| 283 |
|
|
| 284 |
|
|
| 285 |
|
|
| 286 |
|
|
| 287 |
|
|
| 288 |
|
|
| 289 |
|
|
| 290 |
|
|
| 291 |
|
|
| 251 | 292 |
|
| 252 | 293 |
|
| 253 | 294 |
|
lib/openagents/repositories/github_projection.ex modified +40
@@ -3,6 +3,7 @@ defmodule OpenAgents.Repositories.GitHubProjection do
| 3 | 3 |
|
| 4 | 4 |
|
| 5 | 5 |
|
| 6 |
|
|
| 6 | 7 |
|
| 7 | 8 |
|
| 8 | 9 |
|
@@ -49,6 +50,45 @@ defmodule OpenAgents.Repositories.GitHubProjection do
| 49 | 50 |
|
| 50 | 51 |
|
| 51 | 52 |
|
| 53 |
|
|
| 54 |
|
|
| 55 |
|
|
| 56 |
|
|
| 57 |
|
|
| 58 |
|
|
| 59 |
|
|
| 60 |
|
|
| 61 |
|
|
| 62 |
|
|
| 63 |
|
|
| 64 |
|
|
| 65 |
|
|
| 66 |
|
|
| 67 |
|
|
| 68 |
|
|
| 69 |
|
|
| 70 |
|
|
| 71 |
|
|
| 72 |
|
|
| 73 |
|
|
| 74 |
|
|
| 75 |
|
|
| 76 |
|
|
| 77 |
|
|
| 78 |
|
|
| 79 |
|
|
| 80 |
|
|
| 81 |
|
|
| 82 |
|
|
| 83 |
|
|
| 84 |
|
|
| 85 |
|
|
| 86 |
|
|
| 87 |
|
|
| 88 |
|
|
| 89 |
|
|
| 90 |
|
|
| 91 |
|
|
| 52 | 92 |
|
| 53 | 93 |
|
| 54 | 94 |
|
lib/openagents_web/controllers/repository_controller.ex modified +43
@@ -7,6 +7,35 @@ defmodule OpenAgentsWeb.RepositoryController do
| 7 | 7 |
|
| 8 | 8 |
|
| 9 | 9 |
|
| 10 |
|
|
| 11 |
|
|
| 12 |
|
|
| 13 |
|
|
| 14 |
|
|
| 15 |
|
|
| 16 |
|
|
| 17 |
|
|
| 18 |
|
|
| 19 |
|
|
| 20 |
|
|
| 21 |
|
|
| 22 |
|
|
| 23 |
|
|
| 24 |
|
|
| 25 |
|
|
| 26 |
|
|
| 27 |
|
|
| 28 |
|
|
| 29 |
|
|
| 30 |
|
|
| 31 |
|
|
| 32 |
|
|
| 33 |
|
|
| 34 |
|
|
| 35 |
|
|
| 36 |
|
|
| 37 |
|
|
| 38 |
|
|
| 10 | 39 |
|
| 11 | 40 |
|
| 12 | 41 |
|
@@ -131,6 +160,20 @@ defmodule OpenAgentsWeb.RepositoryController do
| 131 | 160 |
|
| 132 | 161 |
|
| 133 | 162 |
|
| 163 |
|
|
| 164 |
|
|
| 165 |
|
|
| 166 |
|
|
| 167 |
|
|
| 168 |
|
|
| 169 |
|
|
| 170 |
|
|
| 171 |
|
|
| 172 |
|
|
| 173 |
|
|
| 174 |
|
|
| 175 |
|
|
| 176 |
|
|
| 134 | 177 |
|
| 135 | 178 |
|
| 136 | 179 |
|
lib/openagents_web/router.ex modified +1
@@ -801,6 +801,7 @@ defmodule OpenAgentsWeb.Router do
| 801 | 801 |
|
| 802 | 802 |
|
| 803 | 803 |
|
| 804 |
|
|
| 804 | 805 |
|
| 805 | 806 |
|
| 806 | 807 |
|
priv/api-contracts/repositories-v1.json modified +2
@@ -9,6 +9,7 @@
| 9 | 9 |
|
| 10 | 10 |
|
| 11 | 11 |
|
| 12 |
|
|
| 12 | 13 |
|
| 13 | 14 |
|
| 14 | 15 |
|
@@ -17,6 +18,7 @@
| 17 | 18 |
|
| 18 | 19 |
|
| 19 | 20 |
|
| 21 |
|
|
| 20 | 22 |
|
| 21 | 23 |
|
| 22 | 24 |
|
priv/docs/rest-api.md modified +7
@@ -27,6 +27,7 @@ the API origin, load your stored credential, and return JSON.
| 27 | 27 |
|
| 28 | 28 |
|
| 29 | 29 |
|
| 30 |
|
|
| 30 | 31 |
|
| 31 | 32 |
|
| 32 | 33 |
|
@@ -36,6 +37,12 @@ POST /api/v1/orgs/:org/repos/imports
| 36 | 37 |
|
| 37 | 38 |
|
| 38 | 39 |
|
| 40 |
|
|
| 41 |
|
|
| 42 |
|
|
| 43 |
|
|
| 44 |
|
|
| 45 |
|
|
| 39 | 46 |
|
| 40 | 47 |
|
| 41 | 48 |
|
test/openagents_web/controllers/project_controller_test.exs modified +42
@@ -1333,6 +1333,48 @@ defmodule OpenAgentsWeb.ProjectControllerTest do
| 1333 | 1333 |
|
| 1334 | 1334 |
|
| 1335 | 1335 |
|
| 1336 |
|
|
| 1337 |
|
|
| 1338 |
|
|
| 1339 |
|
|
| 1340 |
|
|
| 1341 |
|
|
| 1342 |
|
|
| 1343 |
|
|
| 1344 |
|
|
| 1345 |
|
|
| 1346 |
|
|
| 1347 |
|
|
| 1348 |
|
|
| 1349 |
|
|
| 1350 |
|
|
| 1351 |
|
|
| 1352 |
|
|
| 1353 |
|
|
| 1354 |
|
|
| 1355 |
|
|
| 1356 |
|
|
| 1357 |
|
|
| 1358 |
|
|
| 1359 |
|
|
| 1360 |
|
|
| 1361 |
|
|
| 1362 |
|
|
| 1363 |
|
|
| 1364 |
|
|
| 1365 |
|
|
| 1366 |
|
|
| 1367 |
|
|
| 1368 |
|
|
| 1369 |
|
|
| 1370 |
|
|
| 1371 |
|
|
| 1372 |
|
|
| 1373 |
|
|
| 1374 |
|
|
| 1375 |
|
|
| 1376 |
|
|
| 1377 |
|
|
| 1336 | 1378 |
|
| 1337 | 1379 |
|
| 1338 | 1380 |
|
test/openagents_web/controllers/repository_controller_test.exs modified +78
@@ -202,6 +202,84 @@ defmodule OpenAgentsWeb.RepositoryControllerTest do
| 202 | 202 |
|
| 203 | 203 |
|
| 204 | 204 |
|
| 205 |
|
|
| 206 |
|
|
| 207 |
|
|
| 208 |
|
|
| 209 |
|
|
| 210 |
|
|
| 211 |
|
|
| 212 |
|
|
| 213 |
|
|
| 214 |
|
|
| 215 |
|
|
| 216 |
|
|
| 217 |
|
|
| 218 |
|
|
| 219 |
|
|
| 220 |
|
|
| 221 |
|
|
| 222 |
|
|
| 223 |
|
|
| 224 |
|
|
| 225 |
|
|
| 226 |
|
|
| 227 |
|
|
| 228 |
|
|
| 229 |
|
|
| 230 |
|
|
| 231 |
|
|
| 232 |
|
|
| 233 |
|
|
| 234 |
|
|
| 235 |
|
|
| 236 |
|
|
| 237 |
|
|
| 238 |
|
|
| 239 |
|
|
| 240 |
|
|
| 241 |
|
|
| 242 |
|
|
| 243 |
|
|
| 244 |
|
|
| 245 |
|
|
| 246 |
|
|
| 247 |
|
|
| 248 |
|
|
| 249 |
|
|
| 250 |
|
|
| 251 |
|
|
| 252 |
|
|
| 253 |
|
|
| 254 |
|
|
| 255 |
|
|
| 256 |
|
|
| 257 |
|
|
| 258 |
|
|
| 259 |
|
|
| 260 |
|
|
| 261 |
|
|
| 262 |
|
|
| 263 |
|
|
| 264 |
|
|
| 265 |
|
|
| 266 |
|
|
| 267 |
|
|
| 268 |
|
|
| 269 |
|
|
| 270 |
|
|
| 271 |
|
|
| 272 |
|
|
| 273 |
|
|
| 274 |
|
|
| 275 |
|
|
| 276 |
|
|
| 277 |
|
|
| 278 |
|
|
| 279 |
|
|
| 280 |
|
|
| 281 |
|
|
| 282 |
|
|
| 205 | 283 |
|
| 206 | 284 |
|
| 207 | 285 |
|