Skip to content
Back to skills

Dev Ext Infrastructure

ASecurity

Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations

  • 29 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 3, 2026
ai-agentsjavascriptrustjavabashsqlapidatabase

Works with

  • api

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add systempromptio/systemprompt-template --skill dev-ext-infrastructure --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev Ext Infrastructure?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dev Ext Infrastructure
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/systempromptio-dev-ext-infrastructure/badge)](https://www.skillsdirectory.com/skills/systempromptio-dev-ext-infrastructure)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "Extension: Infrastructure"
description: "Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations"
---

# Extension: Infrastructure

Infrastructure traits provide background processing, database schemas, API routes, asset management, authentication, and config validation.

---

## 1. Jobs

Background tasks that run on schedule or on demand.

### Trait

```rust
#[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 }
}
```

### Schedule Format

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 |

### Running Jobs Manually

```bash
systemprompt infra jobs run {job_name}
systemprompt infra jobs list
```

### Registration

```rust
impl Extension for MyExtension {
    fn jobs(&self) -> Vec<Arc<dyn Job>> {
        vec![Arc::new(MyJob)]
    }
}
```

---

## 2. Schemas

Database table definitions embedded in extensions at compile time.

```rust
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"]
    }
}
```

### Schema Conventions

| 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` |

---

## 3. Router

HTTP API endpoints provided by extensions.

```rust
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.

---

## 4. Assets

CSS, JavaScript, fonts, and images provided by extensions.

```rust
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")),
        ]
    }
}
```

### Asset Pipeline

```
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)
```

---

## 5. Storage Paths

Directories required by the extension under `storage/files/`.

```rust
impl Extension for MyExtension {
    fn required_storage_paths(&self) -> Vec<String> {
        vec!["documents".into(), "exports".into()]
    }
}
```

---

## 6. Site Authentication

```rust
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()],
        })
    }
}
```

---

## 7. Config Validation

```rust
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)
    }
}
```

---

## 8. Rules

| 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` |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.