Formato de Pack
Resumen
Sección titulada «Resumen»Un archivo .gtpack es un archivo firmado que contiene flows, componentes y recursos para Greentic.
Estructura de Archivo
Sección titulada «Estructura de Archivo»my-feature.gtpack├── manifest.cbor # Pack metadata (CBOR encoded)├── flows/ # Flow definitions│ ├── main.ygtc│ └── helper.ygtc├── components/ # WASM components│ └── processor.wasm├── assets/ # Static assets│ ├── templates/│ └── cards/├── sbom.json # Software Bill of Materials└── signature.sig # Ed25519 signatureEsquema de Manifest
Sección titulada «Esquema de Manifest»El archivo manifest.cbor contiene los metadatos del pack en formato CBOR:
struct PackManifest { name: String, version: String, description: Option<String>, authors: Vec<String>, capabilities: Capabilities, flows: HashMap<String, FlowEntry>, components: HashMap<String, ComponentEntry>, assets: HashMap<String, AssetEntry>, dependencies: HashMap<String, VersionReq>, secrets: SecretsConfig, created_at: u64, content_hash: String,}
struct Capabilities { id: String, provides: Vec<String>,}
struct FlowEntry { path: String, hash: String,}
struct ComponentEntry { path: String, hash: String, interface: Option<String>,}
struct AssetEntry { path: String, hash: String,}
struct SecretsConfig { required: Vec<String>, optional: Vec<String>,}Especificación de pack.toml
Sección titulada «Especificación de pack.toml»Esquema Completo
Sección titulada «Esquema Completo»[pack]name = "my-feature"version = "1.0.0"description = "Feature description"authors = ["Name <email>"]license = "MIT"repository = "https://github.com/org/repo"homepage = "https://example.com"readme = "README.md"
[capabilities]id = "greentic.cap.app.v1"provides = ["feature-name"]
[dependencies]greentic-templates = "^0.4"greentic-llm-openai = "^0.4"
[flows]main = "flows/main.ygtc"setup = "flows/setup.ygtc"# key = path
[components]processor = "components/processor.wasm"# key = path
[assets]templates = "assets/templates/"cards = "assets/cards/"# key = directory
[secrets]required = ["api_key", "bot_token"]optional = ["webhook_secret"]
[config]# Default configuration valuesdefault_model = "gpt-4"max_retries = 3IDs de Capability
Sección titulada «IDs de Capability»Identificadores estándar de capability:
| ID de Capability | Propósito |
|---|---|
greentic.cap.app.v1 | Pack de aplicación |
greentic.cap.messaging.provider.v1 | Proveedor de mensajería |
greentic.cap.events.provider.v1 | Proveedor de eventos |
greentic.cap.component.v1 | Componente reutilizable |
greentic.cap.tool.v1 | Herramienta MCP |
Hashing de Contenido
Sección titulada «Hashing de Contenido»Todo el contenido del pack se resume con BLAKE3:
content_hash = blake3( flows_hash || components_hash || assets_hash)
flows_hash = blake3( flow1_hash || flow2_hash || ...)Formato de Firma
Sección titulada «Formato de Firma»Los packs se firman con Ed25519:
signature.sig:- Algorithm: Ed25519- Message: content_hash- Format: Raw 64-byte signatureVerificación:
let public_key = load_public_key("publisher.pub");let signature = pack.read_signature();let content_hash = pack.compute_content_hash();
verify(&public_key, content_hash, signature)?;Formato SBOM
Sección titulada «Formato SBOM»Software Bill of Materials en formato SPDX JSON:
{ "spdxVersion": "SPDX-2.3", "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "my-feature-sbom", "packages": [ { "name": "my-feature", "version": "1.0.0", "downloadLocation": "https://example.com" } ], "relationships": []}Compresión
Sección titulada «Compresión»El contenido del pack se comprime con zstd en nivel 3:
let compressed = zstd::encode_all(contents, 3)?;Compatibilidad de Versiones
Sección titulada «Compatibilidad de Versiones»La versión del formato de pack se almacena en el manifest:
struct PackManifest { pack_format_version: u32, // Currently: 1 // ...}Carga de Packs
Sección titulada «Carga de Packs»Proceso de carga de packs en runtime:
- Extract archive - Descomprimir zstd
- Parse manifest - Decodificar metadatos CBOR
- Verify signature - Comprobar firma Ed25519
- Validate hashes - Verificar integridad del contenido
- Check capabilities - Asegurar capability compatible
- Load flows - Analizar definiciones de flow YAML
- Instantiate components - Cargar módulos WASM
- Register - Añadir al registro de runtime
División de Operaciones de Componentes
Sección titulada «División de Operaciones de Componentes»Cuando los flows hacen referencia a un componente WASM con una operación (por ejemplo, component-templates.render), el compilador de packs almacena la cadena completa "component-id.operation" como un único ID de componente en el manifest. En runtime, el cargador divide este valor en el último punto para extraer por separado el ID del componente y el nombre de la operación.
Por ejemplo, un nodo de flow que hace referencia a component-templates.render:
- Stored in manifest:
"component-templates.render"(clave única) - Runtime resolution: se divide en el componente
component-templatesy la operaciónrender
Esta estrategia de división usa el último punto como delimitador, lo que permite que los propios IDs de componente contengan puntos sin ambigüedad. Luego, el runtime busca el componente por su ID extraído e invoca la operación especificada en el módulo WASM cargado.
Manifest key Component ID Operation───────────────────────────────── ─────────────────────── ──────────component-templates.render → component-templates rendercomponent-llm-openai.chat → component-llm-openai chatorg.custom.my-tool.execute → org.custom.my-tool executeEste comportamiento es transparente para los autores de flows; los flows simplemente hacen referencia a component-id.operation en la configuración del nodo, y el compilador de packs y el runtime se encargan del resto.
Referencia de CLI
Sección titulada «Referencia de CLI»# Build packgreentic-pack build ./my-pack --output my-feature.gtpack
# Sign packgreentic-pack sign my-feature.gtpack --key signing-key.pem
# Verify packgreentic-pack verify my-feature.gtpack --pubkey publisher.pub
# Inspect packgreentic-pack info my-feature.gtpack
# Extract packgreentic-pack extract my-feature.gtpack --output ./extracted/