ワンクリックで
extension-infrastructure
Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Search the web for information using the WebSearch tool
Demonstrates governance blocking when plaintext secrets are detected in tool inputs
A simple demonstration skill that searches the web for information
Demonstration skill that attempts to use a plaintext secret, designed to be blocked by governance hooks
List, message, configure, and restart agents via the systemprompt CLI
View traffic, costs, agent stats, and bot detection via the systemprompt CLI
| name | Extension: Infrastructure |
| description | Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations |
Infrastructure traits provide background processing, database schemas, API routes, asset management, authentication, and config validation.
Background tasks that run on schedule or on demand.
#[async_trait]
pub trait Job: Send + Sync {
fn name(&self) -> &'static str;
fn schedule(&self) -> &'static str;
fn tags(&self) -> Vec<&'static str>;
async fn execute(&self, ctx: &dyn JobContext) -> Result<JobResult>;
fn enabled(&self) -> bool { true }
fn run_on_startup(&self) -> bool { false }
}
Cron syntax: seconds minutes hours day_of_month month day_of_week
| Example | Meaning |
|---|---|
0 0 * * * * | Every hour |
0 0 3 * * * | Daily at 3 AM |
0 */15 * * * * | Every 15 minutes |
systemprompt infra jobs run {job_name}
systemprompt infra jobs list
impl Extension for MyExtension {
fn jobs(&self) -> Vec<Arc<dyn Job>> {
vec![Arc::new(MyJob)]
}
}
Database table definitions embedded in extensions at compile time.
impl Extension for MyExtension {
fn schemas(&self) -> Vec<SchemaDefinition> {
vec![SchemaDefinition::inline("my_table", include_str!("../schema/my_table.sql"))]
}
fn migration_weight(&self) -> u32 { 100 }
fn dependencies(&self) -> Vec<&'static str> {
vec!["users"]
}
}
| Convention | Rule |
|---|---|
| Primary key | id UUID PRIMARY KEY DEFAULT gen_random_uuid() |
| Timestamps | Always TIMESTAMPTZ, never TIMESTAMP |
| Indexes | Create for frequently queried columns |
| Naming | snake_case for tables and columns |
| Schema file | {crate}/schema/{table_name}.sql |
HTTP API endpoints provided by extensions.
impl Extension for MyExtension {
fn router(&self, ctx: &dyn ExtensionContext) -> Option<ExtensionRouter> {
let db = ctx.database().clone();
let router = axum::Router::new()
.route("/my-endpoint", axum::routing::get(handle_get))
.route("/my-endpoint", axum::routing::post(handle_post))
.with_state(db);
Some(ExtensionRouter::new("/api/ext/my-extension", router))
}
}
Extension routes should mount under /api/ext/ to avoid colliding with core routes.
CSS, JavaScript, fonts, and images provided by extensions.
impl Extension for MyExtension {
fn declares_assets(&self) -> bool { true }
fn required_assets(&self, paths: &dyn AssetPaths) -> Vec<AssetDefinition> {
vec![
AssetDefinition::css("my-styles.css", include_bytes!("../assets/my-styles.css")),
]
}
}
storage/files/css/ <- CSS source
storage/files/js/ <- JS source
extensions/web/src/assets.rs <- Register assets
web/dist/ <- Output (generated by copy_extension_assets)
Directories required by the extension under storage/files/.
impl Extension for MyExtension {
fn required_storage_paths(&self) -> Vec<String> {
vec!["documents".into(), "exports".into()]
}
}
impl Extension for MyExtension {
fn site_auth(&self) -> Option<SiteAuthConfig> {
Some(SiteAuthConfig {
protected_paths: vec!["/admin".into()],
login_redirect: "/admin/login".into(),
exclude_paths: vec!["/admin/login".into()],
})
}
}
impl Extension for MyExtension {
fn config_prefix(&self) -> Option<&str> { Some("my_extension") }
fn validate_config(&self, config: &Value) -> Result<ValidationReport> {
let mut report = ValidationReport::new();
if config.get("api_key").is_none() {
report.add_error("my_extension.api_key is required");
}
Ok(report)
}
}
| Rule | Rationale |
|---|---|
Jobs must return JobResult | Enables tracking in scheduler |
Schemas use include_str!() | Compile-time embedding |
| Migration weight 100+ for extensions | Core uses 1-40 |
Router endpoints under /api/ext/ | Avoid collisions |
All SQL uses TIMESTAMPTZ | Never TIMESTAMP |