Repository navigation
v1.2.0: Access groups, join cycles, and Trino
SLayer 1.2.0
A release about access control, messier real-world schemas, and one more Tier 1 database.
Per-caller model access. You can now tag models with access_tags and give each caller a filtered view of your store. A caller sees a model only if it is untagged or shares one of their tags. Models that read a hidden model are hidden as well, and so are memories that only mention hidden models. For that caller, a hidden model behaves exactly like one that does not exist.
Trino is Tier 1. Install it with pip install 'motley-slayer[trino]'. Date shifts, relative date ranges, week buckets and time spines now work on Trino, and the same fixes apply to Presto and Athena. Query timeouts and HTTPS logins on any port now work on Trino.
Schemas with foreign-key cycles ingest fully. A single FK cycle used to strip every join from the whole schema. Now every FK becomes a join. When two FKs point at the same table, ingestion names the joins after their columns, so you can query billing_address.city and shipping_address.city from orders.
Better join routing. When several join paths are possible, SLayer now picks the one with the fewest fan-out joins. A saved measure that joins back to your query's source model now works instead of failing with a round-trip error.
Also: Postgres uuid and jsonb columns ingest as text without warnings, and MCP query validation errors now name the actual problem instead of three unrelated ones.
Breaking: query-backed models no longer store backing_query_sql. Run a dry_run query to see the SQL. Saving a derived column or model filter whose path crosses an ambiguous join is now an error.
Additional technical details
- Access control: wrap a backend with
TagFilteredStorage(backend, tags={...}, bypass=False)and pass it as the engine's storage. Every reader (listing, search, inspect, root inference, the SQL facade catalog,validate_models) sees the filtered view. Writes by non-bypass callers merge onto the full stored model; a write that conflicts with hidden content raisesHiddenContentConflictError, and only bypass callers may set or changeaccess_tags(AccessTagsEditError). Saving a model that reads a more narrowly tagged model emits anarrowed_accesswarning, collected into MCPcreate_model/edit_modelreplies. - Storage backends: new
StorageBackend.cache_identity(); the defaultgraph_fingerprint()is nowNone(never reused). The YAML and SQLite backends compute exact fingerprints. The v15 migration dropsbacking_query_sqlfrom stored models. - Joins:
edit_modelacceptsremove.join_edges: [{target_model, name, join_pairs}]to remove one of several joins to the same target. Schema drift drops only the broken edge. Canonical paths inrecommend_root_model, routing suggestions, the facade catalog and the OSI converter now use edge names. Ambiguous derived-column paths raiseDerivedColumnAmbiguousErrorat save time. - MCP: the
queryargument's JSON schema changes fromanyOftooneOf(string = saved model name, object = query, array = stages). cypher_filternow has a 10 s timeout and runs off the event loop.