pwn 0.5.783 → 0.5.785
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +8 -8
- data/README.md +37 -0
- data/Rakefile +19 -1
- data/bin/pwn +2 -1
- data/bin/pwn_setup +1 -1
- data/bin/pwn_web_cache_deception +35 -7
- data/build_gem.sh +1 -1
- data/documentation/AI-Integration.md +7 -5
- data/documentation/Agent-Tool-Registry.md +2 -2
- data/documentation/Backup-Retention.md +82 -0
- data/documentation/Configuration.md +10 -6
- data/documentation/Contributing.md +1 -1
- data/documentation/Cron.md +64 -35
- data/documentation/Diagrams.md +2 -2
- data/documentation/General-PWN-Usage.md +4 -3
- data/documentation/Home.md +6 -5
- data/documentation/How-PWN-Works.md +7 -6
- data/documentation/Installation.md +254 -10
- data/documentation/Mission-Cancellation.md +134 -0
- data/documentation/Operability.md +17 -0
- data/documentation/Persistence.md +8 -6
- data/documentation/Plugin-Degradation.md +12 -0
- data/documentation/Plugins.md +3 -2
- data/documentation/Reinforcement-Learning.md +5 -6
- data/documentation/Runtime-Source-Protection.md +162 -0
- data/documentation/Transparent-Browser.md +11 -0
- data/documentation/Troubleshooting.md +3 -2
- data/documentation/What-is-PWN.md +2 -2
- data/documentation/YubiKey-Vaults.md +183 -0
- data/documentation/YubiKey.md +339 -0
- data/documentation/diagrams/cron-scheduling.svg +130 -128
- data/documentation/diagrams/dot/cron-scheduling.dot +5 -5
- data/documentation/diagrams/dot/persistence-filesystem.dot +5 -3
- data/documentation/diagrams/dot/plugin-ecosystem.dot +2 -2
- data/documentation/diagrams/persistence-filesystem.svg +172 -142
- data/documentation/diagrams/plugin-ecosystem.svg +64 -64
- data/documentation/pwn-ai-Agent.md +10 -4
- data/etc/default_cron/session_cleanup.rb +1245 -22
- data/etc/default_skills/pwn/ai/agent/mission_namespace/SKILL.md +21 -0
- data/etc/default_skills/pwn/ai/agent/tools/browser_act/SKILL.md +45 -0
- data/etc/default_skills/pwn/ai/agent/tools/loot_query/SKILL.md +27 -26
- data/etc/default_skills/pwn/ai/agent/tools/recon_run/SKILL.md +25 -15
- data/etc/default_skills/pwn/ai/agent/tools/workspace_tool/SKILL.md +24 -0
- data/etc/default_skills/pwn/ai/server_tools/SKILL.md +25 -0
- data/etc/default_skills/pwn/backups/SKILL.md +54 -0
- data/etc/default_skills/pwn/plugins/recon/SKILL.md +12 -1
- data/etc/default_skills/pwn/plugins/yubikey/SKILL.md +157 -0
- data/etc/default_skills/pwn/plugins/yubikey/fido/SKILL.md +189 -0
- data/etc/default_skills/pwn/plugins/yubikey/hsmauth/SKILL.md +83 -0
- data/etc/default_skills/pwn/plugins/yubikey/management/SKILL.md +80 -0
- data/etc/default_skills/pwn/plugins/yubikey/oath/SKILL.md +115 -0
- data/etc/default_skills/pwn/plugins/yubikey/openpgp/SKILL.md +144 -0
- data/etc/default_skills/pwn/plugins/yubikey/otp/SKILL.md +97 -0
- data/etc/default_skills/pwn/plugins/yubikey/piv/SKILL.md +110 -0
- data/etc/default_skills/pwn/plugins/yubikey/protocol/SKILL.md +21 -0
- data/etc/default_skills/pwn/plugins/yubikey/security_domain/SKILL.md +75 -0
- data/etc/default_skills/pwn/plugins/yubikey/security_domain/scp/SKILL.md +46 -0
- data/etc/default_skills/pwn/plugins/yubikey/transport/SKILL.md +98 -0
- data/etc/default_skills/pwn/redaction/SKILL.md +13 -1
- data/lib/pwn/ai/agent/dispatch.rb +26 -15
- data/lib/pwn/ai/agent/extrospection.rb +6 -7
- data/lib/pwn/ai/agent/learning.rb +62 -25
- data/lib/pwn/ai/agent/loop.rb +17 -1
- data/lib/pwn/ai/agent/mission_namespace.rb +331 -0
- data/lib/pwn/ai/agent/policy.rb +5 -0
- data/lib/pwn/ai/agent/policy_evaluation.rb +8 -8
- data/lib/pwn/ai/agent/prompt_builder.rb +13 -2
- data/lib/pwn/ai/agent/request_runtime.rb +122 -18
- data/lib/pwn/ai/agent/reward.rb +5 -3
- data/lib/pwn/ai/agent/skill_consolidation.rb +3 -2
- data/lib/pwn/ai/agent/skill_review.rb +9 -5
- data/lib/pwn/ai/agent/swarm.rb +35 -16
- data/lib/pwn/ai/agent/tools/browser_act.rb +32 -0
- data/lib/pwn/ai/agent/tools/loot_query.rb +11 -1
- data/lib/pwn/ai/agent/tools/recon_run.rb +11 -1
- data/lib/pwn/ai/agent/tools/workspace_tool.rb +29 -0
- data/lib/pwn/ai/agent/turn_finalizer.rb +6 -2
- data/lib/pwn/ai/agent.rb +1 -0
- data/lib/pwn/ai/anthropic.rb +8 -33
- data/lib/pwn/ai/cli.rb +34 -5
- data/lib/pwn/ai/gemini.rb +1 -0
- data/lib/pwn/ai/grok.rb +39 -28
- data/lib/pwn/ai/ollama.rb +4 -2
- data/lib/pwn/ai/open_ai.rb +11 -32
- data/lib/pwn/ai/open_web_ui.rb +62 -4
- data/lib/pwn/ai/router.rb +53 -3
- data/lib/pwn/ai/server_tools.rb +231 -0
- data/lib/pwn/ai.rb +1 -0
- data/lib/pwn/backups.rb +347 -0
- data/lib/pwn/config.rb +70 -39
- data/lib/pwn/cron.rb +120 -49
- data/lib/pwn/migrate.rb +150 -68
- data/lib/pwn/module_skills.rb +7 -0
- data/lib/pwn/plugins/ai_sandbox.rb +538 -1
- data/lib/pwn/plugins/authentication_helper.rb +74 -4
- data/lib/pwn/plugins/basic_auth.rb +2 -1
- data/lib/pwn/plugins/binary_parser.rb +5 -4
- data/lib/pwn/plugins/ghidra.rb +4 -3
- data/lib/pwn/plugins/google_workspace.rb +4 -21
- data/lib/pwn/plugins/jobs.rb +1 -1
- data/lib/pwn/plugins/log.rb +21 -3
- data/lib/pwn/plugins/preflight_checker.rb +34 -9
- data/lib/pwn/plugins/recon.rb +4 -1
- data/lib/pwn/plugins/repl/ai.rb +305 -27
- data/lib/pwn/plugins/repl/ai_console.rb +273 -89
- data/lib/pwn/plugins/repl/ai_swarm.rb +181 -62
- data/lib/pwn/plugins/repl/mesh.rb +3 -16
- data/lib/pwn/plugins/repl/vault.rb +4 -15
- data/lib/pwn/plugins/repl.rb +1 -216
- data/lib/pwn/plugins/sandbox/driver.rb +4 -0
- data/lib/pwn/plugins/transparent_browser.rb +215 -0
- data/lib/pwn/plugins/vault.rb +412 -135
- data/lib/pwn/plugins/yubikey/fido.rb +1288 -0
- data/lib/pwn/plugins/yubikey/hsmauth.rb +439 -0
- data/lib/pwn/plugins/yubikey/management.rb +686 -0
- data/lib/pwn/plugins/yubikey/oath.rb +766 -0
- data/lib/pwn/plugins/yubikey/openpgp.rb +1063 -0
- data/lib/pwn/plugins/yubikey/otp.rb +897 -0
- data/lib/pwn/plugins/yubikey/piv.rb +1315 -0
- data/lib/pwn/plugins/yubikey/protocol.rb +341 -0
- data/lib/pwn/plugins/yubikey/security_domain/scp.rb +482 -0
- data/lib/pwn/plugins/yubikey/security_domain.rb +464 -0
- data/lib/pwn/plugins/yubikey/transport.rb +1017 -0
- data/lib/pwn/plugins/yubikey.rb +844 -0
- data/lib/pwn/plugins.rb +1 -0
- data/lib/pwn/redaction.rb +69 -12
- data/lib/pwn/session_trace.rb +4 -0
- data/lib/pwn/sessions.rb +58 -16
- data/lib/pwn/setup.rb +123 -41
- data/lib/pwn/version.rb +1 -1
- data/lib/pwn/www/app_cobalt_io.rb +16 -5
- data/lib/pwn/www/bug_crowd.rb +16 -5
- data/lib/pwn/www/coinbase_pro.rb +16 -5
- data/lib/pwn/www/github.rb +30 -14
- data/lib/pwn/www/paypal.rb +15 -4
- data/lib/pwn/www/synack.rb +16 -5
- data/lib/pwn/www/twitter.rb +17 -6
- data/lib/pwn.rb +1 -0
- data/scripts/build_gate.rb +58 -0
- data/spec/documentation/installation_md_spec.rb +1 -1
- data/spec/fixtures/yubikey/apdu_frames.json +162 -0
- data/spec/integration/authentication_helper_oath_spec.rb +117 -0
- data/spec/integration/build_gate_spec.rb +73 -0
- data/spec/integration/controller_spill_spec.rb +48 -0
- data/spec/integration/harness_process_spec.rb +97 -0
- data/spec/integration/mission_cancel_spec.rb +79 -0
- data/spec/integration/mission_curses_pty_spec.rb +44 -0
- data/spec/integration/persistence_roundtrip_spec.rb +1 -7
- data/spec/integration/readme_security_spec.rb +47 -0
- data/spec/integration/web_cache_deception_yubikey_spec.rb +159 -0
- data/spec/lib/pwn/ai/agent/dispatch_spec.rb +6 -3
- data/spec/lib/pwn/ai/agent/dispatch_vault_safety_spec.rb +86 -0
- data/spec/lib/pwn/ai/agent/injection_guard_spec.rb +2 -0
- data/spec/lib/pwn/ai/agent/learning_spec.rb +4 -4
- data/spec/lib/pwn/ai/agent/loop_artifacts_spec.rb +5 -0
- data/spec/lib/pwn/ai/agent/loop_spec.rb +104 -29
- data/spec/lib/pwn/ai/agent/mission_namespace_spec.rb +138 -0
- data/spec/lib/pwn/ai/agent/policy_spec.rb +27 -0
- data/spec/lib/pwn/ai/agent/request_runtime_spec.rb +48 -0
- data/spec/lib/pwn/ai/agent/shell_search_effect_spec.rb +44 -0
- data/spec/lib/pwn/ai/agent/solve_spec.rb +6 -4
- data/spec/lib/pwn/ai/agent/tools/browser_act_spec.rb +44 -0
- data/spec/lib/pwn/ai/agent/tools/loot_query_yubikey_spec.rb +55 -0
- data/spec/lib/pwn/ai/agent/tools/recon_run_yubikey_spec.rb +43 -0
- data/spec/lib/pwn/ai/agent/tools/workspace_tool_spec.rb +20 -0
- data/spec/lib/pwn/ai/agent/turn_finalizer_spec.rb +7 -0
- data/spec/lib/pwn/ai/anthropic_vault_enrollment_spec.rb +37 -0
- data/spec/lib/pwn/ai/cli_spec.rb +6 -9
- data/spec/lib/pwn/ai/oauth_vault_persistence_spec.rb +195 -0
- data/spec/lib/pwn/ai/open_ai_spec.rb +2 -2
- data/spec/lib/pwn/ai/open_web_ui_workspace_spec.rb +36 -0
- data/spec/lib/pwn/ai/router_spec.rb +31 -3
- data/spec/lib/pwn/ai/server_tools_spec.rb +39 -0
- data/spec/lib/pwn/backups_spec.rb +114 -0
- data/spec/lib/pwn/config_redaction_yubikey_spec.rb +28 -0
- data/spec/lib/pwn/config_yubikey_spec.rb +92 -0
- data/spec/lib/pwn/cron_spec.rb +113 -6
- data/spec/lib/pwn/migrate_spec.rb +108 -5
- data/spec/lib/pwn/migrate_yubikey_spec.rb +128 -0
- data/spec/lib/pwn/module_skills_spec.rb +8 -0
- data/spec/lib/pwn/plugins/ai_sandbox_spec.rb +230 -0
- data/spec/lib/pwn/plugins/authentication_helper_native_yubikey_spec.rb +40 -0
- data/spec/lib/pwn/plugins/authentication_helper_yubikey_spec.rb +90 -0
- data/spec/lib/pwn/plugins/capability_broker/daemon_spec.rb +1 -1
- data/spec/lib/pwn/plugins/google_workspace_spec.rb +17 -35
- data/spec/lib/pwn/plugins/log_spec.rb +7 -0
- data/spec/lib/pwn/plugins/log_yubikey_spec.rb +47 -0
- data/spec/lib/pwn/plugins/preflight_checker_native_yubikey_spec.rb +19 -0
- data/spec/lib/pwn/plugins/preflight_checker_yubikey_spec.rb +55 -0
- data/spec/lib/pwn/plugins/recon_yubikey_spec.rb +43 -0
- data/spec/lib/pwn/plugins/repl/ai_console_spec.rb +125 -78
- data/spec/lib/pwn/plugins/repl/ai_legacy_containment_spec.rb +200 -0
- data/spec/lib/pwn/plugins/repl/ai_swarm_spec.rb +30 -16
- data/spec/lib/pwn/plugins/repl/ai_vault_edit_yubikey_spec.rb +103 -0
- data/spec/lib/pwn/plugins/repl/ai_yubikey_spec.rb +48 -0
- data/spec/lib/pwn/plugins/repl/mesh_vault_persistence_spec.rb +149 -0
- data/spec/lib/pwn/plugins/repl/vault_yaml_serialization_spec.rb +11 -0
- data/spec/lib/pwn/plugins/repl/vault_yubikey_spec.rb +39 -0
- data/spec/lib/pwn/plugins/repl_spec.rb +56 -5
- data/spec/lib/pwn/plugins/transparent_browser_jev_spec.rb +46 -0
- data/spec/lib/pwn/plugins/vault_native_yubikey_spec.rb +29 -0
- data/spec/lib/pwn/plugins/vault_publication_safety_spec.rb +258 -0
- data/spec/lib/pwn/plugins/vault_store_safety_spec.rb +241 -0
- data/spec/lib/pwn/plugins/vault_yubikey_safety_spec.rb +168 -0
- data/spec/lib/pwn/plugins/vault_yubikey_spec.rb +128 -0
- data/spec/lib/pwn/plugins/vault_yubikey_vector_spec.rb +45 -0
- data/spec/lib/pwn/plugins/yubikey/fido_spec.rb +854 -0
- data/spec/lib/pwn/plugins/yubikey/hsmauth_spec.rb +235 -0
- data/spec/lib/pwn/plugins/yubikey/management_spec.rb +277 -0
- data/spec/lib/pwn/plugins/yubikey/oath_spec.rb +349 -0
- data/spec/lib/pwn/plugins/yubikey/openpgp_spec.rb +810 -0
- data/spec/lib/pwn/plugins/yubikey/otp_spec.rb +337 -0
- data/spec/lib/pwn/plugins/yubikey/piv_spec.rb +646 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_secure_spec.rb +28 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_spec.rb +149 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_vectors_spec.rb +18 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain/scp_spec.rb +256 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain/support.rb +153 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain_spec.rb +296 -0
- data/spec/lib/pwn/plugins/yubikey/transport_spec.rb +760 -0
- data/spec/lib/pwn/plugins/yubikey_security_spec.rb +260 -0
- data/spec/lib/pwn/plugins/yubikey_spec.rb +209 -0
- data/spec/lib/pwn/plugins/yubikey_terminal_spec.rb +147 -0
- data/spec/lib/pwn/redaction_spec.rb +13 -10
- data/spec/lib/pwn/redaction_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/session_cleanup_concurrency_spec.rb +201 -0
- data/spec/lib/pwn/session_cleanup_default_spec.rb +167 -2
- data/spec/lib/pwn/session_cleanup_legacy_spec.rb +101 -0
- data/spec/lib/pwn/session_cleanup_payload_spec.rb +335 -2
- data/spec/lib/pwn/session_cleanup_recovery_spec.rb +403 -0
- data/spec/lib/pwn/sessions_spec.rb +112 -0
- data/spec/lib/pwn/setup_native_yubikey_spec.rb +66 -0
- data/spec/lib/pwn/setup_spec.rb +3 -1
- data/spec/lib/pwn/setup_vault_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/setup_yubikey_spec.rb +40 -0
- data/spec/lib/pwn/www/login_yubikey_spec.rb +273 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/gate_failure_formatter.rb +14 -0
- data/spec/support/harness/cli_faults.rb +13 -9
- data/spec/support/harness/controller_spill.rb +26 -0
- data/spec/support/harness/controller_state.rb +54 -0
- data/spec/support/harness/evaluate.rb +12 -1
- data/spec/support/harness/experiments.rb +1 -1
- data/spec/support/harness/fake_provider.rb +22 -6
- data/spec/support/harness/fault_preload.rb +3 -1
- data/spec/support/harness/mission_console.rb +54 -0
- data/spec/support/harness/mission_curses_pty.rb +41 -0
- data/spec/support/harness/mission_dispatch.rb +30 -0
- data/spec/support/harness/mission_fixture_preload.rb +24 -0
- data/spec/support/harness/mission_job_lifetime.rb +25 -0
- data/spec/support/harness/mission_legacy.rb +25 -0
- data/spec/support/harness/mission_normal_exit.rb +34 -0
- data/spec/support/harness/mission_swarm.rb +23 -0
- data/spec/support/harness/mission_unsupported.rb +29 -0
- data/spec/support/harness/package_acceptance.rb +33 -5
- data/spec/support/harness/session_acceptance.rb +4 -4
- data/spec/support/harness/swarm_acceptance.rb +1 -1
- data/spec/support/harness/swarm_control.rb +44 -0
- data/spec/support/mission_namespace.rb +14 -0
- data/spec/support/mission_pipe_queue.rb +33 -0
- data/third_party/pwn_rdoc.jsonl +599 -15
- metadata +140 -17
data/documentation/Home.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **PWN** (/pōn/) - an open-source offensive-security automation framework and
|
|
4
4
|
> continuous-security-integration platform written in Ruby.
|
|
5
|
-
>
|
|
5
|
+
> 108 plugins · 48 SAST modules · 90 AWS wrappers · 22 WWW drivers · 56 CLI
|
|
6
6
|
> executables · 6 LLM engines · a self-improving multi-agent AI · one REPL.
|
|
7
7
|
|
|
8
8
|
**Repo root:** `/opt/pwn` · **This wiki:** `/opt/pwn/documentation/` ·
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
| [How PWN Works](How-PWN-Works.md) | The five layers, with the architecture diagram |
|
|
20
20
|
| [Installation](Installation.md) | `gem install --verbose pwn` → `pwn setup` doctor/provisioner · capability profiles · `--migrate` state doctor |
|
|
21
21
|
| [General Usage](General-PWN-Usage.md) | Day-one cheat sheet |
|
|
22
|
-
| [Operability and Evidence](Operability.md) |
|
|
22
|
+
| [Operability and Evidence](Operability.md) | Runtime writes, backups, cron, completion and deployment boundaries |
|
|
23
23
|
| [Configuration](Configuration.md) | `~/.pwn/pwn.yaml` (encrypted) - engines, keys, agent options · `pwn-vault` |
|
|
24
24
|
| **[All Data-Flow Diagrams](Diagrams.md)** | **29 SVGs** in one scrollable page |
|
|
25
25
|
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
| | |
|
|
38
38
|
|---|---|
|
|
39
39
|
| [AI / LLM Integration](AI-Integration.md) | OpenAI · Anthropic · Grok (OAuth) · Gemini · Ollama · Open WebUI |
|
|
40
|
-
| [Agent Tool Registry](Agent-Tool-Registry.md) | 16 toolsets · **
|
|
40
|
+
| [Agent Tool Registry](Agent-Tool-Registry.md) | 16 toolsets · **152** LLM-callable tools |
|
|
41
41
|
| [Memory · Skills · Learning](Skills-Memory-Learning.md) | Introspection, reviewed skill updates and bundled SOP/module skills on first launch |
|
|
42
42
|
| [Mistakes](Mistakes.md) | **Negative feedback** - fingerprint failures · do-NOT-repeat · `[REPEATING]`/`[REGRESSED]` · inline self-correction |
|
|
43
43
|
| [Reinforcement Learning](Reinforcement-Learning.md) | **`Reward` + `Curriculum` + `Policy`** - outcome/process judges · preference ledger · self-play practice · live Q / REINFORCE (advisory) · export-ready LoRA gate |
|
|
@@ -45,19 +45,20 @@
|
|
|
45
45
|
| [Swarm (Multi-Agent)](Swarm.md) | Personas · ask · debate · broadcast · shared bus |
|
|
46
46
|
| [Sessions](Sessions.md) | Transcript persistence + reflection |
|
|
47
47
|
| [Session Workflow](Session-Workflow.md) | Keywords: `continue` / last session / write-then-read |
|
|
48
|
-
| [Cron](Cron.md) | Scheduled jobs.
|
|
48
|
+
| [Cron](Cron.md) | Scheduled jobs. Fresh install seeds one `session_cleanup` coordinator; curriculum is not seeded |
|
|
49
49
|
|
|
50
50
|
## 🧩 Capability Namespaces (`lib/pwn/*`)
|
|
51
51
|
|
|
52
52
|
| | |
|
|
53
53
|
|---|---|
|
|
54
|
-
| [Plugins (
|
|
54
|
+
| [Plugins (108)](Plugins.md) | Every `PWN::Plugins::*` module by category |
|
|
55
55
|
| ↳ [BurpSuite](BurpSuite.md) ⭐ | Preferred web proxy / scanner |
|
|
56
56
|
| ↳ [TransparentBrowser](Transparent-Browser.md) | Headless / visible browser automation |
|
|
57
57
|
| ↳ [NmapIt](NmapIt.md) | Network discovery |
|
|
58
58
|
| ↳ [Metasploit](Metasploit.md) | RPC exploitation |
|
|
59
59
|
| ↳ [Fuzzing](Fuzzing.md) | `Fuzz` · `Sock` · `Packet` |
|
|
60
60
|
| ↳ [Hardware](Hardware.md) | Serial · BusPirate · MSR206 · Android · BareSIP |
|
|
61
|
+
| ↳ [YubiKey](YubiKey.md) | Device management, hardware vaults and OATH MFA |
|
|
61
62
|
| [SAST (48 rules)](SAST.md) | Static analysis + test-case engine |
|
|
62
63
|
| [WWW (22 drivers)](WWW.md) | Browser automations for real sites |
|
|
63
64
|
| [AWS (90 services)](AWS.md) | Cloud-security enumeration |
|
|
@@ -20,7 +20,7 @@ hardware).
|
|
|
20
20
|
| `pwn --ai PROMPT` | `bin/pwn` | Headless one-shot agent (CI-friendly) |
|
|
21
21
|
| `pwn setup` | `lib/pwn/setup.rb` · `bin/pwn_setup` | Post-install doctor + capability provisioner + `--migrate` state doctor (also `pwn --setup[=PROFILE]`) |
|
|
22
22
|
| `bin/` (including `pwn-ai` and `pwn-capd`) | 56 files | Thin OptionParser wrappers plus the `pwn` REPL / one-shot agent |
|
|
23
|
-
| `PWN::Cron` | `lib/pwn/cron.rb` | Scheduled jobs + background worker (`pwn setup`). Fresh install seeds
|
|
23
|
+
| `PWN::Cron` | `lib/pwn/cron.rb` | Scheduled jobs + background worker (`pwn setup`). Fresh install seeds one `session_cleanup` housekeeping coordinator; curriculum schedules require explicit creation. Existing schedules are preserved |
|
|
24
24
|
|
|
25
25
|
## L2 - AI agent core (`lib/pwn/ai/agent/`)
|
|
26
26
|
|
|
@@ -28,7 +28,7 @@ hardware).
|
|
|
28
28
|
|---|---|
|
|
29
29
|
| `Loop` | plan → **TaskSummarizer** briefs → dispatch tool_calls → observe → repeat until `may_finalize?`. No iteration-budget abort |
|
|
30
30
|
| **`TaskSummarizer`** | Executive UX: every request gets an English task compass (`emit_plan!` · `about_to` as `task k/n`) - no statement/question/goal type |
|
|
31
|
-
| `Registry` | JSON-Schema function definitions grouped into 16 **toolsets** · **
|
|
31
|
+
| `Registry` | JSON-Schema function definitions grouped into 16 **toolsets** · **152 tools** · `CORE_TOOLS` = `DEFAULT_PREFERENCE` (`memory_recall` · `session_recall` · `skills_recall` · `pwn_eval` · `shell` · `mistakes_record` · `mistakes_resolve` · `learning_note_outcome` · `memory_remember` · `skills_update` · `artifact_read` · `artifact_grep` · `job_run` · `job_status` · `job_tail` · `job_result` · `job_kill`) |
|
|
32
32
|
| `Dispatch` / `Result` | execute a tool, capture stdout/value/error/duration |
|
|
33
33
|
| `PromptBuilder` | inject MEMORY / SKILLS / LEARNING / **KNOWN MISTAKES + FIXES** / METRICS / **POLICY** / EXTROSPECTION / RECENT TURNS |
|
|
34
34
|
| `Metrics` · `Learning` · `Reflect` · **`Policy`** | **introspection** - how well am I doing? (Policy is live Q / REINFORCE, advisory rank only) |
|
|
@@ -44,7 +44,7 @@ call, and [Reinforcement Learning](Reinforcement-Learning.md) for how
|
|
|
44
44
|
|
|
45
45
|
## L3 - Capability namespaces (`lib/pwn/*`)
|
|
46
46
|
|
|
47
|
-
`Plugins` (
|
|
47
|
+
`Plugins` (108) · `SAST` (48) · `WWW` (22) · `AWS` (90) · `SDR` · `Blockchain` ·
|
|
48
48
|
`Bounty` · `Reports` · `FFI` · `Banner` · **`Setup`** · **`Migrate`**. First launch also seeds bundled skills from `etc/default_skills/`. Each is
|
|
49
49
|
a plain module of `public_class_method def self.x(opts = {})` methods -
|
|
50
50
|
callable the same way from the REPL, from `pwn_eval`, or from a driver.
|
|
@@ -74,9 +74,10 @@ Q / REINFORCE only for eligible resolved outcomes with independently attributed
|
|
|
74
74
|
(MEMORY · SKILLS · LEARNING · KNOWN MISTAKES/FIXES · TOOL EFFECTIVENESS ·
|
|
75
75
|
POLICY · EXTROSPECTION · RECENT TURNS) are re-injected into the next system
|
|
76
76
|
prompt.
|
|
77
|
-
Nightly hygiene
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
Nightly hygiene is the one seeded `session_cleanup` coordinator. It is not three
|
|
78
|
+
separate enabled jobs, and it does not use systemd. Curriculum practice, offline
|
|
79
|
+
judge, and weekly LoRA train are optional templates; they are not seeded, and
|
|
80
|
+
deleting them does not cause the next launch to recreate them.
|
|
80
81
|
|
|
81
82
|
`Metrics.esr` is `verified_exploit_tools / vulnerable_tools`. `Metrics.asr` is `successful_attacks / total_attack_attempts`. `Learning.rsi_tick` compares ESR with the previous snapshot and writes a lesson when it falls. A file hash, a nuclei template match, or a CVE id does not move ESR. Only a reproduced exploit does.
|
|
82
83
|
|
|
@@ -1,5 +1,190 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
+
## Housekeeping deployment and diagnostics
|
|
4
|
+
|
|
5
|
+
The packaged `etc/default_cron/session_cleanup.rb` is the shared implementation
|
|
6
|
+
for `/maintenance run`, `/maintenance dry-run`, `/sessions cleanup`, and the
|
|
7
|
+
managed `session_cleanup` cron job. `/maintenance status` reports physical file
|
|
8
|
+
counts, bytes, configured retention, budgets, incomplete scans and safe error
|
|
9
|
+
classes. These are storage counts, not the session menu's pagination count.
|
|
10
|
+
Curses executes maintenance on its existing command worker, not its render/input
|
|
11
|
+
thread. Ctrl+C requests a safe boundary; committed work is not rolled back.
|
|
12
|
+
|
|
13
|
+
Upgrade the installed gem, run `pwn setup --migrate --fix`, then restart PWN
|
|
14
|
+
clients **and the existing cron worker**. Source-checkout edits alone do not
|
|
15
|
+
update installed endpoints. Schema 11 seeds a version-1 housekeeping policy and
|
|
16
|
+
refreshes the managed helper. Existing job IDs, schedules, disabled states,
|
|
17
|
+
custom Ruby payloads, custom unmarked helpers and policy edits are preserved.
|
|
18
|
+
A custom helper is not automatically upgraded. Fresh setup is idempotent and
|
|
19
|
+
registration never runs cleanup; the default job retains its next-slot guard.
|
|
20
|
+
Startup performs fixed-path checks and coalesces a daily background request in
|
|
21
|
+
`maintenance/background.json`. The existing cron worker consumes it through the
|
|
22
|
+
existing enabled job, never through a second worker. Disabled jobs stay disabled.
|
|
23
|
+
Do not apply maintenance while old untracked clients are running: unknown
|
|
24
|
+
legacy ownership blocks mutation rather than guessing which sessions are active.
|
|
25
|
+
|
|
26
|
+
Storage is organized into logical categories without relocating literal evidence
|
|
27
|
+
anchors:
|
|
28
|
+
|
|
29
|
+
| Category | Existing/new locations under `~/.pwn` | Retention contract |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| sessions | `sessions/` including support and requests | Eligible unsummarized, inactive, unreferenced transcripts only; physical deletion with backups |
|
|
32
|
+
| learning | `learning.jsonl`, `learning/`, `memory*.json`, `mistakes.json`, policy/curriculum/extrospection stores, finetune and preference records | Evidence migration retains exact verified snapshots; unknown records remain protected |
|
|
33
|
+
| artifacts | `artifacts/`, `exports/`, `findings.jsonl`, engagements, corpora and binary workspaces | Durable evidence, not disposable cache |
|
|
34
|
+
| state | `swarm/`, `cron/`, `agents.yml`, `jobs/`, `missions/`, `runs/`, metrics | Preserve continuation associations and active work |
|
|
35
|
+
| logs | `logs/` | Only explicitly registered disposable closed logs are eligible; unknown logs remain |
|
|
36
|
+
| cache | `cache/` | Only producer-registered, checksum-verified, inactive disposable files |
|
|
37
|
+
| tmp | `workspaces/runtime/` | Same registration contract; never glob-delete arbitrary temp files |
|
|
38
|
+
| maintenance | `maintenance/`, legacy `session_cleanup_archive/` | Policy, permanent locks, metadata ledgers and recoverable quarantine |
|
|
39
|
+
|
|
40
|
+
`maintenance/policy.json` is non-secret JSON, version 1. `batch_size` defaults to
|
|
41
|
+
100; `scan_limit` to 100000. Cooperative admission defaults to `work_items: 100000`,
|
|
42
|
+
`work_seconds: 30` and `work_bytes: 67108864` for dependency and maintenance
|
|
43
|
+
payload reads, plus reserved disposable backup writes. Existing policy
|
|
44
|
+
files acquire these defaults in memory, without rewriting operator values.
|
|
45
|
+
`maintenance/layout.json` upgrades recognized inventory v1 or v2 to v3 separately from
|
|
46
|
+
policy; unknown inventory versions are refused. `retention_days` defaults to sessions 0, logs 30,
|
|
47
|
+
cache 7, tmp 1, maintenance 90. Null disables that category's expiry. Session
|
|
48
|
+
age is an additional floor, never an override of leases, provenance or evidence.
|
|
49
|
+
Learning/artifacts/state remain non-expiring: their policy slots are descriptive,
|
|
50
|
+
not authorization to erase evidence. `budget_bytes` enforces pressure eviction
|
|
51
|
+
for verified inactive disposable files (logs 256 MiB, cache 512 MiB, tmp 256 MiB,
|
|
52
|
+
maintenance 1 GiB), including before ordinary expiry. Null retention still
|
|
53
|
+
disables deletion. Budgets never evict protected evidence. Over-budget protected storage needs
|
|
54
|
+
operator review, not automatic deletion. Inventory scans are bounded and report
|
|
55
|
+
incompleteness rather than claiming a complete total. `bytes` counts logical file
|
|
56
|
+
bytes; `unique_bytes` counts each inode once per category. Directory discovery is
|
|
57
|
+
streamed for inventory and dependency trees. Work/time admission is cooperative
|
|
58
|
+
between phases and items, not a hard deadline: an admitted read, hash or atomic
|
|
59
|
+
commit completes. Exhausted/partial dependency indexes block deletion and report
|
|
60
|
+
`incomplete`/`interrupted`. Retrying recomputes dependencies; no timeout kills a writer.
|
|
61
|
+
Disposable cleanup reserves the complete payload transaction before its first
|
|
62
|
+
hash: one bounded read for preview, or five payload-size passes for verification,
|
|
63
|
+
backup read/write, backup verification and final source verification on apply.
|
|
64
|
+
Reads reject size changes and cannot follow unlimited concurrent growth. Quarantine,
|
|
65
|
+
legacy-backup inventory/compaction, atomic-temp recovery and transaction-status
|
|
66
|
+
reads also use byte admission. Policy/cursor metadata and durable ledger writes
|
|
67
|
+
are control overhead, not a hard total-filesystem-I/O quota; directory name
|
|
68
|
+
discovery is not a payload-byte allowance. An oversized item is retained, with
|
|
69
|
+
the overall maintenance run marked `incomplete`/`interrupted`; raise the explicit
|
|
70
|
+
work budget to process it. Once admitted, backup/commit finishes even if the
|
|
71
|
+
deadline expires mid-write.
|
|
72
|
+
|
|
73
|
+
Producer integration uses `PWN::SessionCleanup.register_disposable(path:,
|
|
74
|
+
category:, expires_at:)` after closing a reproducible file. Producers must hold
|
|
75
|
+
its permanent `<path>.lease` exclusively while writing, and readers hold it
|
|
76
|
+
shared throughout use. The registry records exact SHA-256, inode and byte count.
|
|
77
|
+
Changed, unknown, symlinked, active and invalid files are retained with reasons.
|
|
78
|
+
Disposable scans persist a lexical round-robin cursor in
|
|
79
|
+
`maintenance/disposable.cursor`; `scan_limit` bounds inspected manifests per run.
|
|
80
|
+
Completed/missing manifests remain for audit, including normal temporary-producer
|
|
81
|
+
unlinks, but cannot monopolize later scans. Active/changed entries are revisited
|
|
82
|
+
on the next circuit. The cursor is scheduling state only: cleanup never removes
|
|
83
|
+
or relocates registry entries, and rechecks registration bytes under the producer
|
|
84
|
+
lease so a concurrent renewal cannot authorize deletion using an old expiry.
|
|
85
|
+
Dry-run does not advance the cursor. A partial circuit reports `incomplete`.
|
|
86
|
+
Registration is not permission to classify evidence as disposable. Legacy caches
|
|
87
|
+
and logs are not implicitly registered. Transcript compaction/append instead use
|
|
88
|
+
a permanent transcript `.write.lock`; compaction temporary files are unique,
|
|
89
|
+
cleaned in ensure, fsynced and atomically replaced. Corrupt transcripts raise,
|
|
90
|
+
not silently compact into partial transcripts.
|
|
91
|
+
|
|
92
|
+
Ghidra decompile and BinaryParser triage now publish and read their canonical
|
|
93
|
+
caches under permanent leases. Ordinary `Log.append` diagnostics now go to
|
|
94
|
+
`logs/pwn.log`, rotating at 1,024,000 bytes into registered closed segments.
|
|
95
|
+
Debug streams hold a lifetime lease and register after request closure; active
|
|
96
|
+
streams cannot be evicted. Historical `/tmp/pwn.log` and learning logs are not
|
|
97
|
+
implicitly deleted. Cache writes and transcript compaction clean their own
|
|
98
|
+
temporary outputs on failure rather than leaving routine temp garbage.
|
|
99
|
+
|
|
100
|
+
Routine disposable cleanup writes exact private backups and prepared/committed
|
|
101
|
+
ledgers under `maintenance/quarantine/`. Only verified committed disposable
|
|
102
|
+
backups expire after the maintenance retention period or under budget pressure.
|
|
103
|
+
Interrupted `expiry_prepared` operations resume from verified remaining backups.
|
|
104
|
+
Broad operations also have prepared/committed/interrupted metadata ledgers under
|
|
105
|
+
`maintenance/runs/`, exposed by status. Prepared/corrupt ledgers
|
|
106
|
+
and unique evidence are never expired. `prune_legacy_backups` recognizes actual
|
|
107
|
+
committed session snapshots, dependency-removal backups, learning migration and
|
|
108
|
+
continuation-retirement ledgers. After retention or under maintenance pressure it
|
|
109
|
+
reclaims **redundant physical bytes** using checksum/readback-verified atomic
|
|
110
|
+
hardlink replacement. Recovery filenames remain intact; the last copy is never
|
|
111
|
+
removed. Unknown/uncommitted records are excluded. A cross-filesystem link failure
|
|
112
|
+
retains the original. Prepared/committed compaction journals are resumable.
|
|
113
|
+
|
|
114
|
+
`PWN::SessionCleanup.recovery_status(ledger: absolute_ledger_path)` identifies
|
|
115
|
+
supported actions. `recover(ledger:, action:, dry_run: true)` is explicit:
|
|
116
|
+
- `restore`: quarantine or legacy session copies, with no overwrite of different bytes;
|
|
117
|
+
- `rollback`: Learning's validated rollback or an unchanged continuation retirement;
|
|
118
|
+
- `rollback_dependencies`: exact targeted store rollback, after restoring source sessions;
|
|
119
|
+
- `resume`: re-evaluate broad maintenance, resume backup compaction, or re-evaluate
|
|
120
|
+
offline layout migration (apply requires `writers_stopped: true`).
|
|
121
|
+
Use `dry_run: false` only after reviewing the plan. Restoring a metadata ledger
|
|
122
|
+
never undoes data changes. Broad operations have independently committed children,
|
|
123
|
+
not a fictitious all-or-nothing rollback. Unknown schemas require manual review.
|
|
124
|
+
`reorganize` remains explicit and offline; this upgrade does not move existing paths.
|
|
125
|
+
|
|
126
|
+
### Housekeeping acceptance ledger (isolated fixtures)
|
|
127
|
+
|
|
128
|
+
`spec/lib/pwn/session_cleanup_recovery_spec.rb` exercises the actual maintenance
|
|
129
|
+
entry point, without live stores or providers:
|
|
130
|
+
|
|
131
|
+
| Requirement | Regression evidence | Boundary |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| Byte admission precedes disposable payload I/O | Expired 1 MiB cache with `work_bytes: 1024` remains intact; no payload read/hash or backup, run incomplete/interrupted | Cooperative allowance, not a hard filesystem-I/O cap |
|
|
134
|
+
| Repeated bounded scans progress | `scan_limit: 1`, two expired caches and a normally unlinked temporary producer; repeated runs delete both caches and retain all manifests | Registry pathname discovery still enumerates names; inspection is bounded |
|
|
135
|
+
| Active/mutated data remains protected | Held shared lease and changed payload survive while later eligible data is processed; released lease is revisited | Requires cooperating permanent producer leases |
|
|
136
|
+
| Re-registration is not lost | Renewing the same file between discovery and lease acquisition retains it; republished cache survives a later cursor circuit | Cursor never moves/deletes registry records |
|
|
137
|
+
| Admitted commit finishes safely | Deadline expires after backup publication; exact backup and committed child deletion survive, enclosing run is interrupted | Not all-or-nothing rollback |
|
|
138
|
+
| Related quarantine reads respect admission | Expired 1 MiB backup exceeds an 8 KiB work allowance and remains committed/unexpired | Legacy/atomic paths also admit reads; their existing integrity/recovery regressions remain enabled |
|
|
139
|
+
|
|
140
|
+
The completed isolated-HOME `bundle exec rake` gate passed 4,568 examples with
|
|
141
|
+
zero failures and inspected 1,161 files with no RuboCop offenses (exit 0).
|
|
142
|
+
Cancellation regressions distinguish preservation before deletion admission from
|
|
143
|
+
completion of an already-admitted commit; redaction covers the canonical log and
|
|
144
|
+
debug/progress/mirror/stderr/fallback sinks. These are fixture-based verification,
|
|
145
|
+
not live deployment acceptance: no live-store maintenance, installed-helper
|
|
146
|
+
deployment or provider run is implied.
|
|
147
|
+
|
|
148
|
+
### Temporary producer ownership audit
|
|
149
|
+
|
|
150
|
+
The audit covers `Dir.tmpdir`, `Tempfile`, `mktmpdir` and atomic replacement
|
|
151
|
+
call sites, not a filesystem filename sweep:
|
|
152
|
+
- Festival speech input now uses `SessionCleanup.temporary` in `~/.pwn/workspaces/runtime`, with
|
|
153
|
+
a lifetime lease and exact registration. Concurrent calls have unique names;
|
|
154
|
+
normal completion unlinks the input and a crashed consumer leaves registered bytes.
|
|
155
|
+
- Ghidra/BinaryParser canonical cache publication and managed temporary inputs
|
|
156
|
+
journal atomic ownership (inode/device, expected hash, exact target) under
|
|
157
|
+
`maintenance/atomic`. `recover_atomic_temps` rejects active writers, changed or
|
|
158
|
+
partial bytes, missing journals and unknown paths. Routine maintenance applies
|
|
159
|
+
retention; explicit recovery can inspect an abandoned journal immediately.
|
|
160
|
+
- Sandbox/Detonate, GPS, RFID, OSINT bridge and GhidraHeadless work directories,
|
|
161
|
+
GDB stdin, and policy-evaluation/Solve verification trees are scoped block or
|
|
162
|
+
owner-cleaned resources. Old unregistered crash remnants are retained, not
|
|
163
|
+
inferred disposable from a prefix. GhidraHeadless's legacy/custom cache is not
|
|
164
|
+
silently enrolled as a canonical cache.
|
|
165
|
+
- Nmap/Nuclei scan output, proxy HAR, browser screenshots, APK output, Workspace
|
|
166
|
+
downloads, history spill and Burp diagnostics may be unique evidence. Their
|
|
167
|
+
existing literal paths remain; no age-based global `/tmp` cleanup is authorized.
|
|
168
|
+
- OAuth/vault/selection, learning/session/map and SDR image atomic outputs may be
|
|
169
|
+
only-copy state or evidence. Their own ensure/rollback protocols remain; unknown
|
|
170
|
+
remnants are not automatically discarded. Solve lock inodes are permanent.
|
|
171
|
+
This is an intentional ownership/evidence boundary, not a claim that every plugin
|
|
172
|
+
scratch file is automatically reclaimable.
|
|
173
|
+
|
|
174
|
+
Swarm registry retirement alone deliberately keeps its saved conversation.
|
|
175
|
+
The command route exposes `/swarm retire NAME --continuation` explicitly.
|
|
176
|
+
`PWN::AI::Agent::Swarm.retire(name:, swarm_id:, local: true, continuation: true)`
|
|
177
|
+
explicitly retires the inactive association with a backup and prepared/committed
|
|
178
|
+
ledger. It does not itself delete the transcript. A later persona request creates
|
|
179
|
+
a new session; active associations cannot be retired. Persona map writers and
|
|
180
|
+
cleanup share a permanent continuation lock.
|
|
181
|
+
|
|
182
|
+
Safe checks: `/maintenance status` and `/maintenance dry-run` do not call a
|
|
183
|
+
provider. Do not use `run` as a diagnostic on production data without reviewing
|
|
184
|
+
the preview. Permission and disk failures retain recoverable bytes and report
|
|
185
|
+
error classes; no blanket root-directory chmod is attempted.
|
|
186
|
+
|
|
187
|
+
|
|
3
188
|
PWN ships as a **single Ruby gem** whose runtime is 100 % `autoload`ed -
|
|
4
189
|
a plugin whose native extension or OS binary is missing costs nothing until
|
|
5
190
|
you actually touch that constant. That means the install is **two steps**:
|
|
@@ -82,7 +267,7 @@ External toolchain used by
|
|
|
82
267
|
skills/ drift 1 legacy flat file(s) PWN::Config → run --migrate --fix
|
|
83
268
|
...
|
|
84
269
|
|
|
85
|
-
cron worker ok
|
|
270
|
+
cron worker ok internal worker pid=...
|
|
86
271
|
|
|
87
272
|
31 / 36 capabilities usable · 5 degraded
|
|
88
273
|
|
|
@@ -130,7 +315,7 @@ pwn setup --list-profiles
|
|
|
130
315
|
| `vision` | `OCR` · `ScannableCodes` · `Reports` · `extro_vision` · tesseract / zbar / graphviz |
|
|
131
316
|
| `voice` | `PWN::Plugins::Voice` · `extro_voice` · espeak-ng / sox |
|
|
132
317
|
| `exploit` | `Metasploit` · `sqlmap` |
|
|
133
|
-
| `hardware` | `Serial` · `BusPirate` · `Android` · `BareSIP` · `extro_serial` · `extro_telecomm` |
|
|
318
|
+
| `hardware` | `Serial` · `BusPirate` · `Android` · `BareSIP` · `YubiKey` (`ykman`) · `extro_serial` · `extro_telecomm` |
|
|
134
319
|
| `re` | `Radare2` · `GDB` · `ExploitDev` · `Frida` · Android RE (`apktool`/`jadx`) · `pwndbg` · `ropper` · `rizin` |
|
|
135
320
|
| `full` | everything above |
|
|
136
321
|
|
|
@@ -180,7 +365,8 @@ What `--migrate` does:
|
|
|
180
365
|
(`PWN::Migrate::STATE_FILES` - no re-implemented parsers). If the raw
|
|
181
366
|
file has bytes but the owner returned its empty-fallback, the file is
|
|
182
367
|
flagged incompatible.
|
|
183
|
-
3. **Autofix** (with `--fix`):
|
|
368
|
+
3. **Autofix** (with `--fix`): one shared recovery generation under
|
|
369
|
+
`~/.pwn/backup/` (seven folders total; see [Backup Retention](Backup-Retention.md))
|
|
184
370
|
→ ordered schema migrations → per-file repair (quarantine corrupt to
|
|
185
371
|
`~/.pwn/quarantine/`, re-seed missing dirs, strip unparsable JSONL lines,
|
|
186
372
|
convert legacy flat skills to the [agentskills.io](https://agentskills.io)
|
|
@@ -196,9 +382,11 @@ predates the running gem (`PWN::Migrate.needed?`).
|
|
|
196
382
|
Schema `v1` also seeds `PWN::Cron.install_defaults` - the nightly
|
|
197
383
|
`curriculum_practice` and weekly `curriculum_train` self-improvement jobs
|
|
198
384
|
(see [Reinforcement Learning](Reinforcement-Learning.md)). `pwn setup`
|
|
199
|
-
also starts the background cron worker
|
|
200
|
-
|
|
201
|
-
|
|
385
|
+
also starts or reuses the single portable background cron worker. Setup,
|
|
386
|
+
migration and startup seeding never install, enable, repair or remove OS
|
|
387
|
+
scheduler units. Defaults live only in `~/.pwn/cron/jobs.yml`; the worker
|
|
388
|
+
must be running for automatic execution (start it again after reboot with
|
|
389
|
+
`pwn setup --cron`). Manual commands remain available without a worker. Live Policy files (`policy.json`,
|
|
202
390
|
`policy_traj.jsonl`) are created on first agent turn when `ai.agent.policy`
|
|
203
391
|
is on.
|
|
204
392
|
|
|
@@ -208,8 +396,42 @@ in the scheduler's local timezone. First launch also seeds it through
|
|
|
208
396
|
is installed to `~/.pwn/cron/session_cleanup.rb`; managed copies refresh on
|
|
209
397
|
subsequent launches/migrations, while unmarked custom helpers are preserved.
|
|
210
398
|
An existing job named `session_cleanup` keeps its ID, schedule, enabled state,
|
|
211
|
-
payload
|
|
212
|
-
|
|
399
|
+
payload. Legacy native scheduler files are left untouched for an explicit
|
|
400
|
+
operator-approved removal; they are never refreshed or re-enabled by setup.
|
|
401
|
+
New jobs defer cleanup until their first scheduled time, rather than deleting
|
|
402
|
+
during initial catch-up.
|
|
403
|
+
|
|
404
|
+
Fresh installs now seed only this job, with `SessionCleanup.coordinate`: shared
|
|
405
|
+
evidence-first maintenance, memory consolidation, then separate learning,
|
|
406
|
+
mistakes and policy retention phases. Existing split maintenance schedules are
|
|
407
|
+
preserved until explicitly consolidated after a safe matched-code deployment.
|
|
408
|
+
Curriculum schedules require explicit creation; startup and repeat migrations
|
|
409
|
+
never recreate deleted curriculum jobs. See [Cron](Cron.md) for opt-in templates
|
|
410
|
+
and schedule-only deletion. Already-running old binaries must be upgraded before
|
|
411
|
+
their startup/config-refresh hooks can be relied on to honor the new defaults.
|
|
412
|
+
|
|
413
|
+
**Housekeeping never uses systemd or any other native scheduler.**
|
|
414
|
+
`session_cleanup` is the only seeded housekeeping job. It runs only through
|
|
415
|
+
PWN's built-in cron worker or a manual command. Older split names
|
|
416
|
+
(`learning_consolidate_nightly`, `pwn_stores_lean_nightly`) are not seeded and
|
|
417
|
+
are not removed automatically. Native job
|
|
418
|
+
installers explicitly skip them with `housekeeping_internal_only`; this also
|
|
419
|
+
covers renamed payloads that invoke `SessionCleanup` or `session_cleanup.rb`.
|
|
420
|
+
Generic scheduler APIs remain available for unrelated custom jobs. Native
|
|
421
|
+
worker launchers mark their execution context and exclude housekeeping;
|
|
422
|
+
legacy PWN systemd cgroups are also excluded. An inherited terminal
|
|
423
|
+
`INVOCATION_ID` alone is not a scheduler context.
|
|
424
|
+
|
|
425
|
+
Existing installations require an explicit operator decision before stopping
|
|
426
|
+
legacy services or processes. Inventory `pwn-cron-*.timer` and `.service`, map
|
|
427
|
+
job IDs to `jobs.yml`, preserve custom schedules, then (only with approval)
|
|
428
|
+
disable and stop the housekeeping timers/services and the legacy shared
|
|
429
|
+
worker service, archive their unit files/drop-ins, remove those exact files,
|
|
430
|
+
and run the user manager's daemon-reload. Do not remove unrelated custom job
|
|
431
|
+
units or change lingering globally. Coordinate old clients before deploying
|
|
432
|
+
the new code, retain `jobs.yml` unchanged, then start/reuse one internal
|
|
433
|
+
worker and verify its PID and guarded tick. Do not run cleanup to validate
|
|
434
|
+
this transition or re-enable legacy housekeeping units.
|
|
213
435
|
|
|
214
436
|
Cleanup calls a session named only when its persisted metadata has
|
|
215
437
|
`title_source: summary`, a nonblank title and summary, and a positive integer
|
|
@@ -321,6 +543,19 @@ Loop requests and title writers hold independent leases, and crashes release
|
|
|
321
543
|
descriptors automatically. Stale lock contents or reused PIDs confer no ownership.
|
|
322
544
|
Never unlink lock files: that would split the synchronization inode.
|
|
323
545
|
|
|
546
|
+
Routine maintenance supports multiple simultaneously running upgraded clients;
|
|
547
|
+
there is no blanket shutdown requirement. Evidence migration takes exclusive
|
|
548
|
+
nonblocking leases per source transcript through index publication, skips active
|
|
549
|
+
sources (`evidence_migration.deferred_active_sessions`), and revisits them on a
|
|
550
|
+
later run after their writers finish. Unrelated eligible sessions can still be
|
|
551
|
+
removed. A busy Learning writer returns
|
|
552
|
+
`evidence_migration.deferred: learning_writer_active` with `apply_blocked: true`
|
|
553
|
+
rather than waiting or interrupting the writer; retry on a later cron tick or
|
|
554
|
+
manual invocation. The permanent maintenance lock admits one applying owner;
|
|
555
|
+
a second receives `Session maintenance already running` immediately. Title
|
|
556
|
+
workers and durable job dependencies retain their existing protections.
|
|
557
|
+
This is routine maintenance, not the explicitly offline layout migration.
|
|
558
|
+
|
|
324
559
|
Old installed processes cannot be upgraded by refreshing the cron helper alone.
|
|
325
560
|
`legacy_owners` reports launchers without the held PID/start-identity capability
|
|
326
561
|
marker; `unknown_legacy_ownership` means their in-memory session IDs are unknown,
|
|
@@ -347,6 +582,15 @@ rake install # or: rvmsudo rake install (multi-user RVM)
|
|
|
347
582
|
pwn setup --profile full --yes # same provisioner, same data tables
|
|
348
583
|
```
|
|
349
584
|
|
|
585
|
+
The `upgrade_pwn.sh` → `build_gem.sh` validation gate still runs through
|
|
586
|
+
`rvmsudo` on multi-user RVM installations. Its merged stdout/stderr is streamed
|
|
587
|
+
and retained in the invoking user's `~/.pwn/logs/build-gate.log` (mode 0600,
|
|
588
|
+
last 1 MiB, replaced on the next gate). The path is printed before execution
|
|
589
|
+
and on failure; installation does not continue after a failed gate. `rake spec`
|
|
590
|
+
also prints each failure immediately and reports the RSpec child's exit status
|
|
591
|
+
or signal, so a later terminated example cannot hide earlier failure details.
|
|
592
|
+
A signal report is diagnostic evidence, not a claim about who sent the signal.
|
|
593
|
+
|
|
350
594
|
The legacy `./install.sh` / `packer/provisioners/pwn.sh` bash paths still
|
|
351
595
|
work, but they now simply delegate to `pwn setup` - the `case $os` package
|
|
352
596
|
lists have been consolidated into `PWN::Setup::NATIVE_GEMS` / `::TOOLCHAIN`.
|
|
@@ -439,7 +683,7 @@ row as `MISSING` until a key is set.
|
|
|
439
683
|
Everything above is a thin CLI over two autoloaded modules:
|
|
440
684
|
|
|
441
685
|
```ruby
|
|
442
|
-
PWN::Setup.check # → { ok:, native_gems_missing:, toolchain_missing:, state:, pkg_manager:, os:, arch: }
|
|
686
|
+
PWN::Setup.check # → { ok:, native_gems_missing:, toolchain_missing:, state:, pkg_manager:, os:, arch:, native_libraries_missing: }
|
|
443
687
|
PWN::Setup.deps(profile: :web, yes: true) # install, then re-check
|
|
444
688
|
PWN::Setup.list_profiles
|
|
445
689
|
PWN::Setup.migrate(fix: true) # thin wrapper → PWN::Migrate.run
|
|
@@ -474,7 +718,7 @@ Vagrant, CI) picks it up automatically.
|
|
|
474
718
|
```ruby
|
|
475
719
|
pwn[CURRENT_VERSION]:001 >>> PWN::Setup.check[:ok] # => true
|
|
476
720
|
pwn[CURRENT_VERSION]:002 >>> PWN::Migrate.needed? # => false
|
|
477
|
-
pwn[CURRENT_VERSION]:003 >>> PWN::Plugins.constants.count # =>
|
|
721
|
+
pwn[CURRENT_VERSION]:003 >>> PWN::Plugins.constants.count # => 108
|
|
478
722
|
pwn[CURRENT_VERSION]:004 >>> PWN::SAST.constants.count # => 48
|
|
479
723
|
pwn[CURRENT_VERSION]:005 >>> pwn-ai # launches agent TUI
|
|
480
724
|
```
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Mission process lifetime and cancellation
|
|
2
|
+
|
|
3
|
+
## Implemented boundary
|
|
4
|
+
|
|
5
|
+
The curses ordinary-request path, local slash-command workers, each curses
|
|
6
|
+
swarm job, and the non-curses `pwn_ai_run_steerable` entrypoint execute provider,
|
|
7
|
+
controller, and tool work
|
|
8
|
+
in a mission-owned Linux PID namespace. CTRL+C kills
|
|
9
|
+
namespace PID 1 through a pidfd, waits for its supervisor to reap it, joins the
|
|
10
|
+
IPC reader, and only then releases the UI's running state. A process group is
|
|
11
|
+
not the ownership boundary: setsid, double forks, and nested child namespaces
|
|
12
|
+
remain descendants of the mission namespace. Other sessions and unrelated
|
|
13
|
+
processes are not signalled.
|
|
14
|
+
|
|
15
|
+
There is no systemd, cgroup, application compiler, or PGID fallback.
|
|
16
|
+
`PWN::AI::Agent::MissionNamespace` is Ruby code using stdlib Fiddle for Linux pidfds and
|
|
17
|
+
process-death signals. Its runtime prerequisite is **util-linux `unshare`**
|
|
18
|
+
(`pwn setup --profile ai`). Linux user/PID namespaces and pidfds must be enabled;
|
|
19
|
+
unsupported kernels or local policy fail closed with setup guidance.
|
|
20
|
+
|
|
21
|
+
Ruby recreates its timer thread after fork, so creating a user namespace from a
|
|
22
|
+
Ruby fork is not supported. For ordinary launches the controller **execs** an
|
|
23
|
+
`unshare --user --map-current-user --keep-caps` supervisor. That fresh Ruby
|
|
24
|
+
supervisor creates a PID namespace and forks its init. It passes a pidfd back
|
|
25
|
+
through a private Unix socket; the init waits for acknowledgement before running
|
|
26
|
+
any request. Killing the supervisor also kills its init through PDEATHSIG.
|
|
27
|
+
The controller, its cwd, and unrelated embedded PWN REPL modes are unchanged.
|
|
28
|
+
|
|
29
|
+
Curses/native, legacy, slash, swarm and one-shot CLI requests use named,
|
|
30
|
+
serializable descriptors, not serialized Ruby closures. Configuration, loaded
|
|
31
|
+
skill metadata and routing context travel as typed JSON over inherited private
|
|
32
|
+
sockets, never in argv or plaintext staging files. RequestRuntime's tool-worker
|
|
33
|
+
snapshot excludes locks and caller cancellation callbacks; the enclosing owner
|
|
34
|
+
provides cancellation. Replies and events remain JSON with generation fencing.
|
|
35
|
+
Loaded Ruby skill scripts are required in the worker. Embedders with additional
|
|
36
|
+
trusted plugin initializers can explicitly set
|
|
37
|
+
`PWN::AI::Agent::MissionNamespace.bootstrap_requires = ['/absolute/plugin/bootstrap.rb']`.
|
|
38
|
+
Arbitrary monkey patches, IO objects and Proc values are not serializable.
|
|
39
|
+
|
|
40
|
+
For applications explicitly launched in a single-identity user namespace,
|
|
41
|
+
MissionNamespace can fork its PID supervisor directly. This preserves trusted
|
|
42
|
+
in-memory Ruby closures without calling unshare(NEWUSER) from Ruby. The caller
|
|
43
|
+
must bootstrap explicitly with `unshare --user --map-current-user --keep-caps`;
|
|
44
|
+
there is no automatic re-exec of an embedded application. The unit-test runner
|
|
45
|
+
uses this real-kernel mode for in-memory mocks; exec/PTy fixtures explicitly
|
|
46
|
+
force the ordinary descriptor path. Both paths create a real per-mission PID
|
|
47
|
+
namespace and reject unavailable containment.
|
|
48
|
+
|
|
49
|
+
Ordinary-request events carry a generation; swarm child messages carry job
|
|
50
|
+
IDs, and console swarm callbacks carry an epoch invalidated by CTRL+C.
|
|
51
|
+
Provider calls, including ordinary-request title refresh, remain in the child.
|
|
52
|
+
Steering uses a separate JSON control pipe. The UI never deserializes Ruby
|
|
53
|
+
objects from the child.
|
|
54
|
+
|
|
55
|
+
## Detached jobs
|
|
56
|
+
|
|
57
|
+
Detached jobs started by a tool inside a mission inherit that mission's
|
|
58
|
+
namespace. They can continue after the individual tool returns, but **not**
|
|
59
|
+
after mission completion, cancellation, or namespace-owner death. Normal
|
|
60
|
+
mission completion also tears down remaining detached descendants. This is
|
|
61
|
+
intentionally different from cross-session durable jobs. A standalone
|
|
62
|
+
`AISandbox.protect_call` without an enclosing mission creates its own namespace
|
|
63
|
+
and ends that lifetime when the call ends.
|
|
64
|
+
|
|
65
|
+
Existing files and already-submitted remote operations are not rolled back.
|
|
66
|
+
The local process guarantee does not revoke work accepted by an external
|
|
67
|
+
service or remote host. Kernel-blocked uninterruptible I/O may delay reaping;
|
|
68
|
+
the UI must remain busy rather than claim readiness early.
|
|
69
|
+
|
|
70
|
+
## Controller-state separation
|
|
71
|
+
|
|
72
|
+
Tool workers are denied writes to their RequestRuntime artifact/checkpoint
|
|
73
|
+
root, including its spill directories and inherited descriptors. The actual
|
|
74
|
+
worker-symlink -> parent-spill reproducer now fails at the worker's symlink
|
|
75
|
+
with permission denied, and the synthetic source directory remains unchanged.
|
|
76
|
+
The audited controller stores (sessions/traces, transcript artifacts,
|
|
77
|
+
learning/policy/metrics, skills, logs, vault/configuration and mission state) are
|
|
78
|
+
also excluded from worker grants. See the finite writer checklist in
|
|
79
|
+
[Runtime-Source-Protection](Runtime-Source-Protection.md). Unspecified tool
|
|
80
|
+
writes stay in `~/.pwn/workspaces/runtime`; another path is allowed only when
|
|
81
|
+
the original operator request names it. Naming a missing file grants its parent,
|
|
82
|
+
including when that parent contains unrelated unreadable directories, so the
|
|
83
|
+
named file can be created. Controller state and tool output
|
|
84
|
+
workspaces must be disjoint: a parent directory containing protected state
|
|
85
|
+
cannot safely receive a broad Landlock write grant.
|
|
86
|
+
|
|
87
|
+
## Verification and remaining scope
|
|
88
|
+
|
|
89
|
+
RSpec owns the subprocess fixtures under `spec/support/harness/mission_*.rb`.
|
|
90
|
+
`spec/integration/mission_cancel_spec.rb` exercises ordinary console next-request
|
|
91
|
+
readiness and generation fencing, blocked-provider descendants, setsid escape,
|
|
92
|
+
normal-exit double forks, unrelated-process preservation, mission-lived tool
|
|
93
|
+
jobs, swarm cancellation, and fail-closed bootstrap. The namespace-denial
|
|
94
|
+
fixture injects EPERM; namespace creation/teardown tests use the real kernel.
|
|
95
|
+
`spec/integration/controller_spill_spec.rb` exercises actual RequestRuntime,
|
|
96
|
+
Dispatch, sandbox restriction, and parent spill persistence with synthetic paths.
|
|
97
|
+
|
|
98
|
+
Local slash-command maintenance/model/MCP workers now use the same hard process
|
|
99
|
+
ownership. Their completion and UI-state messages are generation-fenced JSON;
|
|
100
|
+
CTRL+C reaps the owner before returning ready. Maintenance already committed
|
|
101
|
+
before cancellation is not rolled back. Model persistence decrypts and encrypts
|
|
102
|
+
in memory; its staging file contains only ciphertext (or is empty). An offline
|
|
103
|
+
SIGKILL regression interrupts encryption startup and verifies unchanged original
|
|
104
|
+
ciphertext and absence of plaintext in the abandoned stage. Native curses PTY
|
|
105
|
+
coverage includes cancellation during a blocked local command and a successful
|
|
106
|
+
next mission.
|
|
107
|
+
|
|
108
|
+
The legacy regex-ReAct fallback now runs its provider/parser/tool loop in the
|
|
109
|
+
same MissionProcess owner. Completed history is transferred by JSON; native
|
|
110
|
+
containment failures are terminal rather than an excuse to retry uncontained.
|
|
111
|
+
Its actual after_read hook and PTY fixture cover detached Ruby/bash descendants,
|
|
112
|
+
CTRL+C, no late writes and a successful next request. Workspace policy
|
|
113
|
+
clarification does not block these offline gates.
|
|
114
|
+
|
|
115
|
+
Native PTY regressions drive actual terminal CTRL+C through both the curses
|
|
116
|
+
console and `pwn_ai_run_steerable`, assert no late descendant writes, then complete
|
|
117
|
+
a second mission. Compiler-free package acceptance builds and installs into a
|
|
118
|
+
private scratch GEM_HOME with compiler/make commands replaced by failing shims,
|
|
119
|
+
activates that exact specification, checks an empty extensions list and no
|
|
120
|
+
mission shared object, then executes a descriptor. Root and nonroot acceptance
|
|
121
|
+
must be reported separately; these are offline checks, not provider or hardware
|
|
122
|
+
evidence.
|
|
123
|
+
|
|
124
|
+
Root loses host-wide DAC override when it enters a user namespace. A host-root
|
|
125
|
+
mission therefore cannot traverse another user's mode-0700 home merely because
|
|
126
|
+
its parent could. Test roots and deployment workspaces must be traversable by
|
|
127
|
+
the mapped host identity. Do not chmod the operator's home to make a fixture
|
|
128
|
+
pass. Filesystem fixtures beneath a private nonroot HOME must use that identity,
|
|
129
|
+
including when their outer test runner is root. The integrated root fixture uses
|
|
130
|
+
an isolated mount namespace: only its task-owned scratch layout is bound at a
|
|
131
|
+
root-traversable path, with HOME, TMPDIR and inherited stdout/stderr logs opened
|
|
132
|
+
inside that layout. Inherited logs opened below the inaccessible real home would
|
|
133
|
+
correctly fail the protected-descriptor preflight. Neither the host mount table
|
|
134
|
+
nor the operator's directory permissions are changed.
|
|
@@ -57,6 +57,23 @@ PKI DMs remain unsupported. Topic `region` is an opaque prefix, not the radio's
|
|
|
57
57
|
regulatory-band setting; `radio_index` is distinct from legacy `channel_num`.
|
|
58
58
|
See [General Usage](General-PWN-Usage.md) and [REPL](pwn-REPL.md).
|
|
59
59
|
|
|
60
|
+
## Current runtime contract
|
|
61
|
+
|
|
62
|
+
These are source contracts. A checkout edit does not change an installed gem or
|
|
63
|
+
a process that is already running. Restart after installing the matching package.
|
|
64
|
+
|
|
65
|
+
| Contract | Current behavior |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| Tool writes | Unspecified `pwn-ai` writes and `TMPDIR` use `~/.pwn/workspaces/runtime`. Another path is writable only when the original operator request names it, including `mv`/`to`. A missing file grants its parent so the file can be created; that parent is still granted when it contains unrelated unreadable directories. `/opt/pwn` and the loaded package stay read-only. |
|
|
68
|
+
| Mission lifetime | CTRL+C kills the mission through `PWN::AI::Agent::MissionNamespace`. That owner is Ruby plus util-linux `unshare` and Linux pidfds. There is no compiled `pwn_mission` extension and no systemd fallback. |
|
|
69
|
+
| Recovery copies | Every PWN recovery producer uses `PWN::Backups` and `~/.pwn/backup/`, seven generation folders total. Adjacent `.bak` files are not the current producer. |
|
|
70
|
+
| Housekeeping | A fresh install seeds one internal `session_cleanup` coordinator. Curriculum jobs are not seeded. Housekeeping never uses systemd. |
|
|
71
|
+
|
|
72
|
+
Details: [Runtime Source Protection](Runtime-Source-Protection.md),
|
|
73
|
+
[Mission Cancellation](Mission-Cancellation.md),
|
|
74
|
+
[Backup Retention](Backup-Retention.md), [Cron](Cron.md),
|
|
75
|
+
[Persistence](Persistence.md).
|
|
76
|
+
|
|
60
77
|
## Deployment and safe verification
|
|
61
78
|
|
|
62
79
|
1. Inspect the intended checkout and preserve existing changes before upgrading.
|
|
@@ -7,8 +7,8 @@ external services and environment overrides can place evidence elsewhere.
|
|
|
7
7
|
|
|
8
8
|
| Path | Owner | Format | Reset tool | Purpose |
|
|
9
9
|
|---|---|---|---|---|
|
|
10
|
-
| `pwn.yaml` | `PWN::Config` · `PWN::Plugins::Vault` | AES-
|
|
11
|
-
| `pwn.yaml.decryptor` | `PWN::Plugins::Vault` | key/IV | - | decrypts `pwn.yaml` (or set `PWN_DECRYPTOR_KEY`/`_IV`) |
|
|
10
|
+
| `pwn.yaml` | `PWN::Config` · `PWN::Plugins::Vault` | Legacy AES-CBC or authenticated YubiKey-derived AES-GCM | `pwn-vault` | engines, keys, agent options; see [hardware vaults](YubiKey-Vaults.md) |
|
|
11
|
+
| `pwn.yaml.decryptor` | `PWN::Plugins::Vault` | Legacy key/IV | - | decrypts legacy `pwn.yaml` (or set `PWN_DECRYPTOR_KEY`/`_IV`); absent for hardware-only vaults |
|
|
12
12
|
| **`.schema`** | **`PWN::Migrate`** | JSON `{schema:,pwn_version:,at:}` | `pwn setup --migrate` | **schema stamp - drives the one-line drift warning on launch** |
|
|
13
13
|
| `memory.json` | `PWN::Memory` | JSON array | `memory_clear` | facts · prefs · lessons · env - injected into every prompt |
|
|
14
14
|
| `memory.idx` | `PWN::MemoryIndex` | JSON `{key → {sha,vec}}` | `PWN::MemoryIndex.reset` | local embedding index over `memory.json` - powers **relevance-ranked** MEMORY injection (incremental; only re-embeds changed entries) |
|
|
@@ -26,7 +26,7 @@ external services and environment overrides can place evidence elsewhere.
|
|
|
26
26
|
| `extrospection/voice/*` | `Extrospection` | wav / txt | `rm -rf` | TTS/STT artifacts from `extro_voice` |
|
|
27
27
|
| `sessions/*.jsonl` | `PWN::Sessions` | JSON-per-line | `sessions_delete` | full transcript per pwn-ai run (with per-step `step_reward` from `Reward.prm`) |
|
|
28
28
|
| `open_goal.json` | `PWN::AI::Agent::OpenGoal` | JSON | delete the file | unfinished host-work request so `continue` / `resume` picks it up |
|
|
29
|
-
| `cron/jobs.yml` | `PWN::Cron` | YAML | `cron_remove` |
|
|
29
|
+
| `cron/jobs.yml` | `PWN::Cron` | YAML | `cron_remove` | Scheduled jobs; fresh install seeds only the `session_cleanup` housekeeping coordinator. Curriculum schedules require explicit creation and are not recreated after deletion |
|
|
30
30
|
| `cron/log/*.log` | `PWN::Cron` | text | rm | last_run output |
|
|
31
31
|
| `agents.yml` | `PWN::AI::Agent::Swarm` | YAML | edit / `agent_spawn` | persona registry |
|
|
32
32
|
| `swarm/<id>/bus.jsonl` | `Swarm` | JSON-per-line | rm -rf | append-only multi-agent chat |
|
|
@@ -34,7 +34,8 @@ external services and environment overrides can place evidence elsewhere.
|
|
|
34
34
|
| `curriculum/` | `PWN::AI::Agent::Curriculum` | JSONL | rm -rf | self-play reproducers · train/gate A/B eval sets |
|
|
35
35
|
| `curriculum_kpi.jsonl` | `PWN::AI::Agent::Curriculum.practice_kpi` | JSONL | rm | outer curriculum KPI snapshots (repeating-mistake trend) |
|
|
36
36
|
| `finetune/*.jsonl` | `Learning.export_finetune` · `Reward.export_dpo` | ShareGPT / OpenAI / DPO JSONL | `rm` | supervised + preference datasets - feed to a LoRA over the local model |
|
|
37
|
-
| `
|
|
37
|
+
| `workspaces/runtime/` | `PWN::Plugins::AISandbox` · `SessionCleanup.temporary` | files | operator-managed | Unspecified `pwn-ai` writes, `TMPDIR`, and registered disposable inputs such as Festival speech. Another path is writable only when the original request names it. `/opt/pwn` stays read-only |
|
|
38
|
+
| `backup/<generation>/` | `PWN::Backups` | shared generations | see [Backup Retention](Backup-Retention.md) | One store, seven generation folders total, for every recovery producer including migrate |
|
|
38
39
|
| `quarantine/` | `PWN::Migrate` | quarantined originals | rm -rf | corrupt/incompatible state files moved aside so the owner re-seeds |
|
|
39
40
|
| `pwn_history` | Pry / pwn-ai | text | operator-managed | Shared durable input history at `~/.pwn/pwn_history` |
|
|
40
41
|
|
|
@@ -69,8 +70,9 @@ for the full `PWN::Migrate` API.
|
|
|
69
70
|
tar czf pwn-state-$(date +%F).tgz -C "$HOME" .pwn
|
|
70
71
|
```
|
|
71
72
|
|
|
72
|
-
`pwn setup --migrate --fix`
|
|
73
|
-
`~/.pwn/backup
|
|
73
|
+
`pwn setup --migrate --fix` admits one generation through `PWN::Backups` under
|
|
74
|
+
`~/.pwn/backup/` before it changes state. That store holds seven generations
|
|
75
|
+
total, not a new unbounded tree per run. See [Backup Retention](Backup-Retention.md).
|
|
74
76
|
|
|
75
77
|
## Start fresh for a new engagement
|
|
76
78
|
|