Pack format
A pack is a connector as one JSON document: its identity, its manifest and every file, keyed by path. Export produces a pack, import accepts one, and it is how you keep a connector in your own source control or move it between tenants. The JSON Schema describes it.
One version
{
"format": 1,
"connector": { "key": "acme-projects", "version": 1, "name": "Acme Projects", "sdk": ">=2", "kind": "http" },
"manifest": { "key": "acme-projects", "version": 1, "name": "Acme Projects", "kind": "http" },
"files": {
"handlers/user/fetchOne.ts": "import type { Handler } from \"../../types.gen.ts\";\n...",
"lib/lookups.ts": "...",
"README.md": "# Acme Projects\n..."
},
"provenance": { "source": "owlie:custom_connector/<connector id>", "revision": "v1", "exported_at": "..." }
}
| Field | Rule |
|---|---|
format | 1 for one version. |
connector.key | A lowercase letter or digit, then lowercase letters, digits, _ and -. Must equal the manifest's key. |
connector.version | The major version. Must equal the manifest's version. |
connector.name | Must equal the manifest's name. |
connector.sdk | >=2. |
connector.kind | http, ldap, scim, sql or flat-file. Must equal the manifest's kind (absent means http). |
manifest | The manifest. For an engine-based kind, the manifest Owlie derives from definition.json, carried as a checked copy: it must match what the engine derives. |
files | Every file, as text, keyed by its relative path. |
provenance | Where the pack came from. Informational; it changes on every export and is not part of the digest. An export sets source to owlie:custom_connector/ plus the connector's id, and revision to v1 for version 1 or v1-draft.3 for the third revision of its draft. |
Files
| Rule | Detail |
|---|---|
| Allowed locations | handlers/, lib/, fixtures/, scripts/, and the files README.md, CHANGELOG.md and definition.json. fixtures/ holds data, such as the Test panel's saved inputs in fixtures/inputs.json; nothing in it runs. |
| Allowed extensions | .ts, .json, .md, .ps1. |
| PowerShell | Only at scripts/<name>.ps1, and scripts/ holds nothing else. See PowerShell scripts for what a script may not do. |
definition.json | Required for LDAP, SCIM, SQL and flat-file connectors; refused for HTTP. |
| Handlers | A file under handlers/ must be a handler path (Handler API). |
| Paths | Forward slashes; not absolute; no . or .. segments, no empty segments, no backslashes. |
| Never included | types.gen.ts and other generated files, tests (*.test.ts), and credentials. Owlie generates types.gen.ts from the manifest at every build, so handlers can import it (as @connector/types, or by relative path) although the pack does not carry it. |
| Imports | The pack's own files, by relative path or as @connector/lib/<path> and @connector/types, and @owlie/connectors/sdk/v2. Nothing else resolves. |
A path segment that starts with __owlie_ is reserved for Owlie's build and refused. The names
__proto__, constructor and prototype are refused as path segments and as keys anywhere in the
manifest.
PowerShell scripts
A script's parameters are data: Owlie hands them to the script as JSON, and nothing may turn them into code. A script is refused when its code (comments and single-quoted strings aside) uses any of these, anywhere, whether or not a parameter is involved:
- text evaluation:
Invoke-Expressionoriex,[ScriptBlock]::Create,.NewScriptBlock(,.InvokeScript(,$ExecutionContext.InvokeCommand,[PowerShell]::Create,.AddScript(,Add-Type; &or.before a variable, an expression in parentheses or a string (& $command), and dot-sourcing a file (. .\lib.ps1);- another process or interpreter:
pwshorpowershellwith options,cmd /c,Start-Process,Invoke-Command,Invoke-Item.
Owlie also puts its own preamble before the script, so a script cannot start with what PowerShell
accepts only first: param(...) (with or without [CmdletBinding()]), using namespace, using module,
using assembly or #requires. Read parameters from $Params instead.
Limits
| Limit | Value |
|---|---|
| All files together | 4 MiB (4,194,304 bytes) |
| One file | 512 KiB (524,288 bytes) |
| Number of files | 512 |
| The manifest | 512 KiB (524,288 bytes) |
Sizes are measured in UTF-8 bytes.
Canonical form and digest
Owlie stores and exports packs in a canonical form: the keys of the document, connector, provenance
and files are sorted, and every file uses LF line endings with exactly one trailing newline. The
manifest keeps its own key order at every level, because order carries meaning (the first identifier
property is the external id unless identifier_paths says otherwise). The pack's digest is the
SHA-256 of the canonical form without provenance, so exporting the same source twice gives the same
digest, and importing unchanged content changes nothing.
Validation
Import checks the document's shape, the rules above, the manifest's schema and the rules that tie
handlers to the manifest (Validation issues), and refuses the document on any
issue. A failed import changes nothing. Import first replaces the document's key and name, in
connector and in the manifest, with those of its target (the new connector you name, or the draft
it replaces), so those two never cause a mismatch.
Publishing runs these checks again and also compiles the handlers, so a pack that imports can still
fail to publish on a compile error. Each import accepts one version (format 1); export and import
work one version at a time.