mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
fix(preview): refuse ~/ in a Docker case; document the folder-route gate
A Docker case is a local session for the file routes, but `~` inside the container is the container's own seeded home. Expanding `~/x.png` on the host opened a different file than the one the agent printed. The attachment POST and POST …/folders now answer 400 for `~/` when the session has `docker` set (absolute paths are unaffected: the workspace is a bind mount). Docs: the resolved-target gate, the route-parameter limit, the listing join rule and the Docker `~/` refusal in architecture-invariants.md, security-architecture.md and CLAUDE.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6bfc1b88d8
commit
3c08971ff8
5 files changed
+68
-5
No files matched your search
@@ -320,6 +320,46 @@ describe('folder grid routes — local folder', () => {
|
||||
expect(res.body).toBe('long-png');
|
||||
});
|
||||
|
||||
// A Docker case is a LOCAL session for the file routes, but its `~` is the
|
||||
// container's home: a separate, seeded directory. `~/x.png` printed inside the
|
||||
// container used to open the HOST's `~/x.png`.
|
||||
describe('~/ in a Docker case', () => {
|
||||
beforeEach(() => {
|
||||
(harness.ctx._session as { docker?: unknown }).docker = {
|
||||
hostId: 'local',
|
||||
label: 'local',
|
||||
engine: 'docker',
|
||||
image: 'codeman-sandbox',
|
||||
containerName: 'codeman-case-test',
|
||||
hostWorkspacePath: root,
|
||||
containerWorkdir: root,
|
||||
network: 'bridge',
|
||||
};
|
||||
});
|
||||
|
||||
it('refuses a ~/ folder, and still lists an absolute one', async () => {
|
||||
const home = await grant('~/renders');
|
||||
expect(home.statusCode).toBe(400);
|
||||
expect(JSON.parse(home.body).error).toMatch(/docker/i);
|
||||
expect((await grant(dir)).statusCode).toBe(200);
|
||||
});
|
||||
|
||||
it('refuses a ~/ attachment, and still registers an absolute one', async () => {
|
||||
const post = (path: string) =>
|
||||
harness.app.inject({ method: 'POST', url: `/api/sessions/${sessionId}/attachments`, payload: { path } });
|
||||
const home = await post('~/renders/old.png');
|
||||
expect(home.statusCode).toBe(400);
|
||||
expect(JSON.parse(home.body).error).toMatch(/docker/i);
|
||||
expect((await post(join(dir, 'old.png'))).statusCode).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps resolving ~/ for a session that is not in a Docker case', async () => {
|
||||
// The contrast: only the Docker case is turned away, `~/` itself still works.
|
||||
const res = await grant('~/this-folder-does-not-exist-codeman-test');
|
||||
expect(res.statusCode).toBe(404);
|
||||
});
|
||||
|
||||
it('404s an unknown folder id and another session’s grant', async () => {
|
||||
const res = await harness.app.inject({
|
||||
method: 'GET',
|
||||
|
||||
Reference in new issue
Block a user