Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,42 @@ jobs:
run: cargo clippy --workspace --all-targets -- -D warnings
- name: cargo test --workspace
run: cargo test --workspace --locked
- name: Validar schemas Tauri (SRC-004)
run: |
python3 -m pip install --no-input --disable-pip-version-check "jsonschema==4.23.0"
python3 tools/validate_tauri_schemas.py

security-runtime:
name: Security runtime deny (G8/G9 / NFR-SEC-001)
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Toolchain pinned (rust-toolchain.toml)
run: rustup show active-toolchain
- name: Instalar deps sistema Tauri/GTK (glib/gdk)
run: |
sudo apt-get update
sudo apt-get install -y \
pkg-config \
libglib2.0-dev \
libgtk-3-dev \
libwebkit2gtk-4.1-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
patchelf
- name: Stub frontendDist para generate_context
run: |
mkdir -p apps/web/dist
printf '%s\n' '<!DOCTYPE html><html><head><meta charset="utf-8"><title>archmaker</title></head><body></body></html>' \
> apps/web/dist/index.html
# Nombre de test obligatorio: si falta, cargo test falla (no skip-if-missing).
- name: Prueba negativa runtime (capability denegada)
run: |
cargo test -p archmaker --locked \
security_runtime_deny_ungranted_command \
-- --nocapture

frontend:
name: Frontend pnpm check (G9)
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"test-a11y:all": "pnpm test-a11y && pnpm test-a11y:axe && pnpm test-a11y:visual && pnpm test-a11y:flow"
},
"dependencies": {
"@tauri-apps/api": "^2",
"@tauri-apps/api": "2.12.1",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
Expand Down
41 changes: 18 additions & 23 deletions crates/archmaker-core/tests/negative_capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,20 @@ fn neg_capability_deny_by_default() {
"permissions vacia: denegacion definitiva; los TOML no conceden"
);

// Check dialog and picker capabilities have empty permissions (reserved for v1)
// MVP: solo main.json. dialog/picker son reserva v1 sin fichero en el árbol.
let caps_dir = repo_root().join("src-tauri/capabilities");
let mut names: Vec<_> = std::fs::read_dir(&caps_dir)
.expect("capabilities dir")
.filter_map(|e| e.ok())
.map(|e| e.file_name().to_string_lossy().into_owned())
.filter(|n| n.ends_with(".json"))
.collect();
names.sort();
assert_eq!(names, vec!["main.json".to_string()], "solo main en MVP");
for cap in ["dialog", "picker"] {
let raw = read_repo(&format!("src-tauri/capabilities/{}.json", cap));
let v: serde_json::Value = serde_json::from_str(&raw).expect("capability JSON invalido");
let perms = v["permissions"]
.as_array()
.expect("permissions debe ser lista");
assert_eq!(
perms.len(),
0,
"{} capability reservado para v1 sin permisos",
cap
assert!(
!caps_dir.join(format!("{cap}.json")).exists(),
"{cap}.json no debe existir en MVP (reserva v1)"
);
}
}
Expand Down Expand Up @@ -408,19 +410,12 @@ fn neg_unknown_window_yields_typed_proto_error() {
}

#[test]
fn dialog_and_picker_deny_everything_by_default() {
// Dialog and picker capabilities are reserved for v1 and have no permissions
fn dialog_and_picker_capability_files_absent_in_mvp() {
let caps_dir = repo_root().join("src-tauri/capabilities");
for cap in ["dialog", "picker"] {
let raw = read_repo(&format!("src-tauri/capabilities/{}.json", cap));
let v: serde_json::Value = serde_json::from_str(&raw).expect("capability JSON invalido");
let perms = v["permissions"]
.as_array()
.expect("permissions debe ser lista");
assert_eq!(
perms.len(),
0,
"{} capability reservado para v1 sin permisos",
cap
assert!(
!caps_dir.join(format!("{cap}.json")).exists(),
"{cap}.json ausente en MVP; reserva documentada en tauri-policy.md"
);
}
}
Expand Down
19 changes: 10 additions & 9 deletions docs/00-governance/source-register.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,19 @@ Toda afirmación mutable (paquetes, versiones, compatibilidad, comportamiento de

## Detalle de captura

| ID | URL canónica | Versión objetivo | Fecha de captura | Verificador | Caducidad / revisión |
| ------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- | ------------------- | ----------------- | ------------------------------------------------------------------------------------- |
| SRC-002 | <https://wiki.archlinux.org/title/Installation_guide> | Contenido wiki vigente a la fecha | 2026-10-05 | Gobierno | Revisar por release de soporte o si cambia el flujo de instalación |
| SRC-003 | <https://github.com/archlinux/archinstall> | Repositorio oficial vigente a la fecha | 2026-10-05 | Gobierno | Revisar antes de fijar el adapter v1 (DEC-003) |
| SRC-004 | <https://v2.tauri.app/> | Tauri 2.x | 2026-10-05 (previa) | Seguridad | Revisar por minor; fijar permisos por ventana |
| SRC-005 | <https://doc.rust-lang.org/stable/> · <https://rustsec.org/> | Rust estable + RustSec Advisory DB | 2026-10-05 | Seguridad | Revisar por release estable y por aviso relevante en `cargo-audit` |
| SRC-006 | <https://json-schema.org/draft/2020-12/release-notes> | Draft 2020-12 | 2026-10-05 | Arquitectura | Estable; revisar notas de errata |
| SRC-007 | <https://www.w3.org/TR/WCAG22/> · <https://www.w3.org/WAI/ARIA/apg/> | **W3C Recommendation 12 December 2024** + ARIA APG vigente | 2026-10-05 | UX/Accesibilidad | Estable; revisar APG por cambios de patrón |
| SRC-008 | <https://slsa.dev/spec/v1.2/> · <https://csrc.nist.gov/pubs/sp/800/218/final> · <https://docs.sigstore.dev/> | **SLSA v1.2** (v1.0 retirada) · **NIST SSDF SP 800-218 v1.1** · Sigstore vigente | 2026-10-05 | Seguridad/Release | Revisar por nueva versión de especificación; fijar versiones antes de firmar releases |
| ID | URL canónica | Versión objetivo | Fecha de captura | Verificador | Caducidad / revisión |
| ------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ----------------- | ------------------------------------------------------------------------------------- |
| SRC-002 | <https://wiki.archlinux.org/title/Installation_guide> | Contenido wiki vigente a la fecha | 2026-10-05 | Gobierno | Revisar por release de soporte o si cambia el flujo de instalación |
| SRC-003 | <https://github.com/archlinux/archinstall> | Repositorio oficial vigente a la fecha | 2026-10-05 | Gobierno | Revisar antes de fijar el adapter v1 (DEC-003) |
| SRC-004 | <https://v2.tauri.app/security/capabilities/> · <https://v2.tauri.app/> | crate `tauri` **=2.12.1** · `tauri-build` **=2.7.1** · CLI/API `@tauri-apps/{cli,api}` **2.12.1** · claimId `CLAIM-SRC-004-CAPABILITIES-2.12.1` · SHA-256 `4a946fe48fbb0c7c535ea53e6070bd8276f3f3d74f96efbaa6d85bd7b53b0f05` | 2026-10-14 | Seguridad | Revisar por minor; regenerar schema y SHA al fijar otra versión |
| SRC-005 | <https://doc.rust-lang.org/stable/> · <https://rustsec.org/> | Rust estable + RustSec Advisory DB | 2026-10-05 | Seguridad | Revisar por release estable y por aviso relevante en `cargo-audit` |
| SRC-006 | <https://json-schema.org/draft/2020-12/release-notes> | Draft 2020-12 | 2026-10-05 | Arquitectura | Estable; revisar notas de errata |
| SRC-007 | <https://www.w3.org/TR/WCAG22/> · <https://www.w3.org/WAI/ARIA/apg/> | **W3C Recommendation 12 December 2024** + ARIA APG vigente | 2026-10-05 | UX/Accesibilidad | Estable; revisar APG por cambios de patrón |
| SRC-008 | <https://slsa.dev/spec/v1.2/> · <https://csrc.nist.gov/pubs/sp/800/218/final> · <https://docs.sigstore.dev/> | **SLSA v1.2** (v1.0 retirada) · **NIST SSDF SP 800-218 v1.1** · Sigstore vigente | 2026-10-05 | Seguridad/Release | Revisar por nueva versión de especificación; fijar versiones antes de firmar releases |

## Notas de verificación

- **SRC-004 (Tauri 2.12.1):** captura de capabilities/permissions en <https://v2.tauri.app/security/capabilities/>. Versiones fijadas en `src-tauri/Cargo.toml` (`tauri` `=2.12.1`, `tauri-build` `=2.7.1` según `Cargo.lock`), `package.json` y `apps/web/package.json` (`@tauri-apps/cli` / `@tauri-apps/api` `2.12.1`). Claim `CLAIM-SRC-004-CAPABILITIES-2.12.1`. Schema ACL: `src-tauri/gen/schemas/desktop-schema.json` con SHA-256 `4a946fe48fbb0c7c535ea53e6070bd8276f3f3d74f96efbaa6d85bd7b53b0f05` (regenerado con `cargo build -p archmaker` el 2026-10-14).
- **SRC-008 (SLSA):** la especificación `v1.0` está **retired**; la versión actual es **v1.2** (<https://slsa.dev/spec/v1.2/>). Toda referencia a SLSA en la documentación debe apuntar a v1.2, no a v1.0.
- **SRC-008 (SSDF):** capturado como **NIST SP 800-218, SSDF Version 1.1** (no v1.0). Las referencias de SDLC se anclan a v1.1.
- **SRC-008 (Sigstore):** capturado el overview oficial; firma/verificación de artefactos (release files, imágenes, binarios, SBOM) conforme a DEC-006.
Expand Down
9 changes: 5 additions & 4 deletions docs/08-security/tauri-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ priority: P0
documentStatus: in-review
approvalStatus: pending
implementationStatus: complete
verificationStatus: not-verified
verificationStatus: partial
releaseStatus: ineligible
owners:
- security
Expand All @@ -16,13 +16,14 @@ reviewers:
# Política Tauri

- Deny-by-default.
- La allow-list JSON de `main`, `dialog` y `picker` permanece vacía: es la denegación definitiva del slice. Los ocho ficheros `src-tauri/permissions/*.toml` definen identificadores `core:*` y no los conceden. `dialog` y `picker` siguen reservadas, sin permisos.
- En MVP solo existe la ventana `main` y su capability (`src-tauri/capabilities/main.json`) con `permissions: []`: esa lista vacía es la denegación definitiva del slice. Los ocho ficheros `src-tauri/permissions/*.toml` definen identificadores `core:*` y no se conceden en el JSON. No hay campo raíz `denied` (el schema Tauri 2 no lo soporta; la ausencia de permiso basta).
- Reserva v1: las ventanas `dialog` y `picker` no tienen ficheros de capability en el árbol MVP; se reintroducirán solo con alcance `accepted` de v1, cada una con allow-list vacía hasta conceder permisos tipados.
- Capabilities separadas por ventana y plataforma.
- Permisos custom con allow/deny explícitos.
- Permisos custom con allow/deny explícitos cuando se concedan.
- Scopes de filesystem mínimos; negar rutas sensibles.
- Sin `shell:*` en MVP.
- Updater solo tras firma y ADR de canal/rollback.
- CSP sin CDN en producción; `default-src 'self'`.
- Devtools desactivadas en release salvo build de diagnóstico controlada.
- Navegación externa mediante allowlist y confirmación.
- Toda capability tiene test negativo.
- Toda capability tiene test negativo (estático + `security-runtime`).
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ license = "Apache-2.0"
rust-version = "1.82"

[build-dependencies]
tauri-build = { version = "2", features = [] }
tauri-build = { version = "=2.7.1", features = [] }

[dependencies]
tauri = { version = "2", features = [] }
tauri = { version = "=2.12.1", features = ["test"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
archmaker-core = { path = "../crates/archmaker-core" }
Expand Down
7 changes: 0 additions & 7 deletions src-tauri/capabilities/dialog.json

This file was deleted.

7 changes: 0 additions & 7 deletions src-tauri/capabilities/picker.json

This file was deleted.

14 changes: 0 additions & 14 deletions src-tauri/gen/schemas/capabilities.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
{
"dialog-capability": {
"identifier": "dialog-capability",
"description": "Deny-by-default: ventana dialog reservada (v1). Sin comandos CorePort en MVP; solo denegaciones explicitas.",
"local": true,
"windows": ["dialog"],
"permissions": []
},
"main-capability": {
"identifier": "main-capability",
"description": "Deny-by-default: permissions vacia es la denegacion definitiva del slice. Los 8 identificadores core:* viven en TOML y no se conceden aqui. Sin shell, sin FS global.",
"local": true,
"windows": ["main"],
"permissions": []
},
"picker-capability": {
"identifier": "picker-capability",
"description": "Deny-by-default: ventana picker reservada (v1). Sin comandos CorePort en MVP; solo denegaciones explicitas.",
"local": true,
"windows": ["picker"],
"permissions": []
}
}
Loading
Loading