From b29dc085371e591b9b8d9963f666d760995212f2 Mon Sep 17 00:00:00 2001 From: AIOSAI Date: Wed, 15 Apr 2026 15:28:16 -0700 Subject: [PATCH] =?UTF-8?q?feat(system):=20DPLAN-0133=20Phase=201=20(part?= =?UTF-8?q?=201/2):=20add=20gitignore=20rule=20for=20apps/integrations/**?= =?UTF-8?q?=20with=20README=20negation,=20plus=20scaffold=20README.md=20in?= =?UTF-8?q?=20all=2010=20core=20branches'=20apps/integrations/=20=E2=80=94?= =?UTF-8?q?=20private=20integration=20space=20is=20now=20leak-proof=20by?= =?UTF-8?q?=20construction.=20Drivers=20and=20wrappers=20dropped=20here=20?= =?UTF-8?q?stay=20local;=20only=20README.md=20is=20tracked.=20See=20DPLAN-?= =?UTF-8?q?0133=20for=20architecture=20rationale=20(three-layer=20design:?= =?UTF-8?q?=20@api=20drivers,=20per-branch=20wrappers,=20public=20generic?= =?UTF-8?q?=20contracts).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: @devpulse --- .gitignore | 7 ++ STATUS.md | 2 +- .../ai_mail/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/api/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/cli/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/drone/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/flow/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/memory/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/prax/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/seedgo/apps/integrations/README.md | 64 +++++++++++++++++++ src/aipass/spawn/apps/integrations/README.md | 64 +++++++++++++++++++ .../trigger/apps/integrations/README.md | 64 +++++++++++++++++++ 12 files changed, 648 insertions(+), 1 deletion(-) create mode 100644 src/aipass/ai_mail/apps/integrations/README.md create mode 100644 src/aipass/api/apps/integrations/README.md create mode 100644 src/aipass/cli/apps/integrations/README.md create mode 100644 src/aipass/drone/apps/integrations/README.md create mode 100644 src/aipass/flow/apps/integrations/README.md create mode 100644 src/aipass/memory/apps/integrations/README.md create mode 100644 src/aipass/prax/apps/integrations/README.md create mode 100644 src/aipass/seedgo/apps/integrations/README.md create mode 100644 src/aipass/spawn/apps/integrations/README.md create mode 100644 src/aipass/trigger/apps/integrations/README.md diff --git a/.gitignore b/.gitignore index 343010f5..605784a3 100644 --- a/.gitignore +++ b/.gitignore @@ -117,3 +117,10 @@ whiteboard.md README_ORIGINAL_DISABLED.md readme_history/ src/aipass/trigger/trigger_data.lock + +# Private integrations — driver layer (@api) and wrapper layer (all branches) +# Per DPLAN-0133. Contents are gitignored; only the scaffold README.md is tracked. +# Drop project-specific code into src/aipass/{branch}/apps/integrations/{project}/ +# It stays local. Never appears in git. +src/aipass/*/apps/integrations/** +!src/aipass/*/apps/integrations/README.md diff --git a/STATUS.md b/STATUS.md index 7392081d..727bf1ae 100644 --- a/STATUS.md +++ b/STATUS.md @@ -300,7 +300,7 @@ ### Friction notes -- **seedgo __init__.py false positive**: `imports: Failed` and `naming: invalid characters` fire on Python reserved filename. Need special-case in seedgo's naming standard and imports standard. Encountered in another project; likely also in AIPass repo. Open a seedgo standard PR when there's bandwidth. +(none active — seedgo __init__.py false positive FIXED by @seedgo in PR #279, 2026-04-14) ### S92 (2026-04-14 ~12:45 PT) — PRE-COMPACT, system prompt reformat work in flight diff --git a/src/aipass/ai_mail/apps/integrations/README.md b/src/aipass/ai_mail/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/ai_mail/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/api/apps/integrations/README.md b/src/aipass/api/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/api/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/cli/apps/integrations/README.md b/src/aipass/cli/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/cli/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/drone/apps/integrations/README.md b/src/aipass/drone/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/drone/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/flow/apps/integrations/README.md b/src/aipass/flow/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/flow/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/memory/apps/integrations/README.md b/src/aipass/memory/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/memory/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/prax/apps/integrations/README.md b/src/aipass/prax/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/prax/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/seedgo/apps/integrations/README.md b/src/aipass/seedgo/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/seedgo/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/spawn/apps/integrations/README.md b/src/aipass/spawn/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/spawn/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale. diff --git a/src/aipass/trigger/apps/integrations/README.md b/src/aipass/trigger/apps/integrations/README.md new file mode 100644 index 00000000..0fab10ce --- /dev/null +++ b/src/aipass/trigger/apps/integrations/README.md @@ -0,0 +1,64 @@ +# apps/integrations/ + +Private integration space for this branch. + +**This folder is gitignored.** Only this README is tracked. Everything else you drop in here stays local and never appears in git, PRs, or the public repo. Safe by construction, not by discipline. + +## What goes here + +**Branch-specific wrappers** that consume external systems via the @api driver layer. Each wrapper handles how THIS branch uses an external system in its own domain. + +``` +apps/integrations/ +└── {project}/ + ├── wrapper.py # How this branch uses the driver + ├── config.json # Optional — local config + └── tests/ # Private tests colocated +``` + +Wrappers should call into `@api`'s generic contracts (e.g. `api.memory_backend.query(...)`), never reference the private project by name in any tracked code. The private project name lives in the @api driver, not here. + +## What does NOT go here + +- **Driver code** — that belongs in `@api/apps/integrations/{project}/driver.py` (the connection layer). +- **Public business logic** — use `apps/modules/` or `apps/handlers/` for that. +- **Drone plugins** — use `apps/plugins/` for those. +- **Secrets** — they live in `~/.secrets/aipass/`, never in the repo. + +## Architecture + +The full design is in DPLAN-0133 (private integrations architecture). Three layers: + +1. **@api driver layer** (`@api/apps/integrations/{project}/`) — owns the physical connection, auth, transport. Knows the private project name. +2. **Per-branch wrapper layer** (`{this_folder}/{project}/`) — owns how this branch consumes the driver's output in its domain. Calls generic contracts, never names private projects. +3. **Public drone commands** (`drone @api integrations list`, `drone @api integrations call `) — advertise the extension points without naming specifics. Fork-safe. + +## Usage + +```python +# Your public code (committed, in apps/modules/ or apps/handlers/) +from aipass.api import memory_backend + +results = memory_backend.query("when did we ship watchdog?") +# memory_backend is a generic contract. In your local setup it routes to whatever +# driver you registered in @api/apps/integrations/. In a fresh clone with nothing +# registered, it returns NotConfigured gracefully. +``` + +```python +# Your private wrapper (in this folder, gitignored) +# apps/integrations/someproject/wrapper.py + +from aipass.api import memory_backend + +def domain_specific_query(context): + """Branch-specific query pattern for domain needs.""" + hint = build_query_from_context(context) + return memory_backend.query(hint, top_k=5, filter={"kind": "decision"}) +``` + +The wrapper stays here, the call into the contract stays here, no private name leaks into tracked code. + +--- + +See DPLAN-0133 for the full design rationale.