serdes-yaml-edit — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited serdes-yaml-edit (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Run both checkers after every edit. No exceptions. Do not batch multiple edits before validating.
clojure -M:run:ee --mode checker --checker structural --export /path/to/export-dir
clojure -M:run:ee --mode checker --checker cards --export /path/to/export-dirIf either checker fails, fix the issue before making further edits.
Serdes YAML uses portable references instead of integer IDs. This is the most important concept for editing.
String name: "Sample Database"
Array of [database, schema, table]:
table_id:
- Sample Database
- PUBLIC
- ACCOUNTSArray of [database, schema, table, field]:
id:
- Sample Database
- PUBLIC
- ACCOUNTS
- EMAILfield_ref:
- field
- - Sample Database
- PUBLIC
- ACCOUNTS
- EMAIL
- nullThe outer array is [field, <field-path>, <options>]. The options are usually null.
Entity ID string (21 characters): "Qk5TgsNx4ubXIUtsQmT8G"
dataset_query:
database: Sample Database
query:
source-table:
- Sample Database
- PUBLIC
- ACCOUNTS
type: queryThese rarely break validation:
name - card/dashboard display namedescription - card/dashboard descriptiondisplay - visualization type (table, bar, line, pie, etc.)visualization_settings - chart configurationarchived - true/falsecollection_id - move to a different collection (use entity_id of target collection, or null for root)These must use valid portable refs and will be caught by the cards checker if wrong:
dataset_query - the query definitionresult_metadata - column metadata (must match the query's output columns)table_id - must reference a table that exists in the exportdatabase_id - must reference a database that exists in the exportEach entry in result_metadata describes an output column. When changing a query's source table or fields, you must update result_metadata to match. Each field entry needs at minimum:
name - column name (e.g., EMAIL)base_type - Metabase type (e.g., type/Text, type/Integer, type/DateTime)display_name - human-readable namefield_ref - portable field referenceid - portable field pathtable_id - portable table pathsource - usually fieldsChange name: at the top level. Safe, no ref changes needed.
Update all of these consistently:
table_id - top-leveldataset_query.query.source-table - in the queryresult_metadata - every field entry's id, field_ref, and table_iddataset_query:
database: Sample Database
query:
source-table:
- Sample Database
- PUBLIC
- ORDERS
filter:
- ">"
- - field
- - Sample Database
- PUBLIC
- ORDERS
- TOTAL
- null
- 100
type: querydisplay: bar # was: tableValid types: table, bar, line, pie, scalar, row, area, combo, scatter, funnel, map, pivot, progress, gauge, waterfall
The export directory IS the reference catalog. When you need to find the correct name for a database, table, or field, look it up directly from the export.
ls databases/Each entry is a database name (directory for serdes format, .yaml for concise format).
ls databases/<db-name>/schemas/<schema>/tables/Example: ls databases/Sample\ Database/schemas/PUBLIC/tables/ shows ACCOUNTS, ORDERS, PRODUCTS, etc.
ls databases/<db-name>/schemas/<schema>/tables/<table>/fields/Example: ls databases/Sample\ Database/schemas/PUBLIC/tables/PRODUCTS/fields/ shows CATEGORY.yaml, TITLE.yaml, PRICE.yaml, etc. The filename (minus .yaml) is the field name.
Card filenames encode the entity ID: <entity-id>_<slug>.yaml. The entity ID is the part before the first underscore (21 characters).
When a checker reports errors, follow this loop:
Do not guess at fixes. Always look up the correct value from the export.
The structural checker validates YAML shape against Malli schemas. Common errors:
Missing required key with typo suggestion:
Missing required key 'name' - found 'nameee' which may be a typoFix: rename the typo'd key back to the correct name. The checker tells you what it expected and what it found.
Wrong type:
'archived' should be a boolean, got: "yes"Fix: use true/false, not strings.
Unknown key:
Unknown key 'foobar' in cardFix: remove the key, or check if it's a typo of a known key.
The cards checker validates that queries resolve against exported metadata. Error types:
UNRESOLVED REFERENCES:
UNRESOLVED REFERENCES:
- field: Sample Database.PUBLIC.PRODUCTS.CATEGORYYYThe dotted path tells you exactly which reference failed. Look up the correct value:
databases/.../tables/<table>/fields/databases/.../schemas/<schema>/tables/databases/ERROR (query construction failed):
ERROR: Error creating query from legacy query: Invalid output: ...Usually means the query structure is malformed. This often follows unresolved references - fix the refs first, then re-check.
ERROR (nil name):
ERROR: Invalid output: {:name ["should be a string, got: nil"]}The card is missing its name field (likely a structural issue that also affects the cards checker).
Card files: collections/<collection-path>/cards/<entity-id>_<slug>.yaml
The filename slug should match the card name (lowercase, underscored). If you rename a card, consider renaming the file to match, though import works on entity_id not filename.
entity_id - this is the identity of the object, changing it creates a new object on importserdes/meta - internal serdes metadata, leave it alonecreated_at - timestamp, no reason to changecreator_id - email reference, leave itmetabase_version - informational, leave it~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.