gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1428Shell 142Markdown 86Rust 842937 Sutichaykuna

⎇ 057332363a7745713f4336f446bccecafff40952 scripts/servidor/claude-caja.sh Shell · 86 siq'ikuna · 5.6 KB Ñawpa willay ch'uya

`/usr/bin/claude` era una COPIA del guion, por eso el arreglo no llegaba 057332363 · Sergio ·

1#!/bin/sh
2# claude — entrar al agente en esta caja. El CLI es glibc y la caja es musl: corre enjaulado
3# (ADR 0015), con el repo, el store, el lab, la memoria y las llaves concedidos y nada más.
4#
5# ── UNA JAULA POR PERSONA, Y SIN PRIVILEGIO ─────────────────────────────────────────────────────
6# `root` usa la instancia `claude`; cada usuario usa `claude-<usuario>`. No es purismo: la instancia
7# concede el HOME de quien entra —su `.claude`, o sea sus credenciales y su memoria— y una sola
8# instancia obligaría a compartirlo. Medido: con la instancia de root, `sergio` muere en
9# `bwrap: Can't mkdir /root/.claude: Permission denied`.
10#
11# ⚠ Y NO se eleva con `doas`/`sudo`: en esta caja **el setuid no toma** («doas: Operation not
12# permitted», con `NoNewPrivs: 0` y `/` sin `nosuid` — queda como deuda entender por qué). No hace
13# falta: `qorpa run` levanta la jaula con user namespaces y anda **sin privilegio**, siempre que el
14# directorio de la instancia sea del usuario.
15#
16# ⚠ LOS BUILDS SIGUEN SIN CORRER DENTRO DE LA JAULA, pero el motivo cambió y conviene tenerlo
17# medido (2026-09-18). Antes, con `root = true`, el bwrap anidado ni se levantaba: «Can't mount proc
18# on /proc». Con `root = false` **sí se levanta y /proc monta** —comprobado—, y lo que ahora falla es
19# otra cosa: el anidado **no puede mapear el uid 0** que `takana build` le pide, porque `sergio` no
20# tiene rango en `/etc/subuid` (sólo lo tiene `root`) y encima `newuidmap`/`newgidmap` **no son
21# setuid** en esta caja (`-r-xr-xr-x`). Resultado: el sandbox del build correría como 1001 y el
22# `install` que escribe `/out` con dueños se cae.
23#
24# ⚠ SE INTENTÓ CERRARLO Y **NO ALCANZÓ** (2026-09-18). Se hicieron las dos cosas obvias:
25#   · rango para `sergio` en `/etc/subuid` y `/etc/subgid` (165536:65536);
26#   · `newuidmap`/`newgidmap` en setuid root **y además** con capacidades (`cap_setuid=ep`).
27# El error se MOVIÓ —ya no dice «no hay rango para sergio»— pero sigue sin mapear:
28#
29#     ⚠ sin mapeo por rango (newuidmap: open of uid_map failed: Permission denied)
30#
31# Lo que quedó descartado, medido: **el setuid sí eleva en esta caja** —sonda en C compilada con el
32# `cc` nuevo: `uid=1001 euid=0`—, `/` no está `nosuid`, y el `uid_map` del proceso es suyo
33# (`-rw-r--r-- sergio:sergio`). O sea que no es ni el rango que faltaba ni el bit que no tomaba.
34# ⚠ Y un detalle que cuesta un rato si no se sabe: **`chown` BORRA el bit setuid**, así que hay que
35# chownear primero y poner el bit después; la primera sonda salió sin bit por ese orden.
36# La causa de fondo queda SIN DETERMINAR, y se dice así en vez de inventarla.
37#
38# Mientras tanto el camino que sí anda es pedírselo al ANFITRIÓN por ssh:
39#
40#   ssh -p 22022 root@127.0.0.1 'cd /opt/takana && flock -o work/.farm-build.lock takana build <r>'
41#
42# ⚠ Y UNA JAULA QUE TE MAPEA A ROOT ROMPE AL PROPIO AGENTE: con `root = true` el CLI se ve uid 0 y
43# **rechaza `--dangerously-skip-permissions`** («cannot be used with root/sudo privileges»). Por eso
44# las instancias de PERSONA van con `root = false` (queda uid 1001 adentro) y con `/store` en `rw`,
45# que es lo que la de `root` ya tenía y a la de `sergio` le faltaba: sin eso el agente lee el store
46# y no puede sellar nada.
47set -eu
48
49# ⚠ `/usr/bin/claude` ES UN ENLACE A ESTE FICHERO, y lo es por algo (2026-09-18): antes era una
50# COPIA, así que arreglar el guion en el repo no cambiaba nada para quien escribe `claude` — el
51# usuario reportó dos veces «sigue abriendo en /opt/takana» con el arreglo ya pusheado y tirado en la
52# caja. Un instalado que es copia DERIVA en silencio y sólo se nota por el síntoma viejo.
53#
54#   ln -sf /opt/takana/scripts/servidor/claude-caja.sh /usr/bin/claude
55_yo="$(id -un)"
56_hogar="${HOME:-/root}"
57_inst="claude"
58[ "$_yo" != "root" ] && _inst="claude-$_yo"
59
60# El `cd` no es comodidad: la memoria del agente se indexa POR RUTA DE TRABAJO. Desde `/` —que es
61# donde `qorpa run` deja el shell— la sesión usa el proyecto `-` y el agente empieza sin saber nada
62# aunque su memoria esté en disco.
63#
64# ⚠ **Y ABRE DONDE ESTÁS PARADO, no en un sitio fijo** (2026-09-18). Antes el destino era
65# `/opt/takana` cableado, así que `cd /work/sergio/takana && claude` abría… `/opt/takana`: el agente
66# contestaba sobre OTRO árbol —el del root— y encima con la memoria de ese proyecto. Se reportó como
67# «entro al repo y claude sigue en /opt/takana», y era literal. Ahora el defecto es `$PWD`; el
68# cableado queda sólo para cuando no hay `PWD` utilizable.
69#
70# `PROY` sigue existiendo para abrirlo sobre otro árbol a propósito:
71#
72#   PROY=/work/sergio/tawasuyu claude
73# ⚠ El `shift 2` no es adorno: sin él, el HOME y el proyecto que se pasan como posicionales se
74# cuelan COMO ARGUMENTOS del agente. Medido: la primera versión abrió la sesión con el prompt
75# «/home/sergio», y el agente contestó —con razón— que eso es una ruta, no un comando.
76# ⚠ El `cd` de adentro FALLA RUIDOSAMENTE: la jaula sólo monta los directorios concedidos, así que
77# desde una ruta no concedida el `cd` no encuentra nada. Antes eso se tragaba con `&&` y el agente
78# arrancaba en `/` sin decir por qué; ahora lo dice y sale.
79_proy="${PROY:-$PWD}"
80[ -d "$_proy" ] || _proy=/opt/takana
81
82exec takana qorpa run "$_inst" -- sh -c \
83  'hogar="$1"; proy="$2"; shift 2
84   cd "$proy" 2>/dev/null || { echo "claude: adentro de la jaula no existe \"$proy\" — ¿está concedido ese directorio en la instancia? (ver grants.dirs)" >&2; exit 1; }
85   exec env HOME="$hogar" TERM="${TERM:-xterm-256color}" /work/claude-cli/2.1.240 "$@"' \
86  _ "$_hogar" "$_proy" "$@"