Repository navigation
Releases: eonity-org/tydal
Release list
TYDAL 1.5.0
Added
- AITY suggestions at the vault write boundary. A gallery
ingestwith
suggest: trueruns AITY on the stored photograph — opt-in per photograph,
because the consumer may hold the photographer's consent for some and not
others. AITY only proposes; what the consumer sent is never changed, and
AITY failing never fails the ingest.GET …/w/suggestions?resources=…
returns the proposed title and description per ingested resource (off,
pending,done,failed) to a key that mayupdate; reading never
starts AITY.
@tydal/clientgetssuggestions(resources). See
docs/architecture/VAULT_WRITE_METHODS.md§3.
Upgrading
No migrations and no new configuration. Suggestions run on the existing AITY
pipeline, so they need what AITY already needs: a configured LLM driver and a
queue worker. @tydal/client goes to 1.7.0 (suggestions);
@tydal/org-mcp and @tydal/vault-mcp keep their versions.
Full changes: v1.4.1...v1.5.0
TYDAL 1.4.1
Added
tools/deploy/server/: the files of a working server setup, ready to
copy — one infrastructure compose (MySQL, Elasticsearch, Redis with a
password, Tika; ports on127.0.0.1, data on a data disk) and, per
installation, a compose file, amake-env.shthat writes the production
backend/.envand creates the database, and an nginx site. With
ELASTICSEARCH_INDEX_PREFIXand the per-installation Redis, cookie and
database names, several installations share one server. DEPLOYMENT.md:
"On a server, by hand".
Changed
- FullFrame, one word. The photo-exhibition product is FullFrame
everywhere: the docs, the help ofexhibitions:setup/exhibitions:create
and the lines they print ("Paste into FullFrame → …", which FullFrame's
user guide quotes), comments and seeders. The CLI guide's section anchor is
now#photo-exhibitions-fullframe.
Upgrading
Nothing to do: documentation, example files and printed text only — no
migrations, no configuration, and @tydal/client, @tydal/org-mcp and
@tydal/vault-mcp keep their versions.
Full changes: v1.4.0...v1.4.1
TYDAL 1.4.0
Added
-
Several installations on one server (#23):
configure.sh <ai> <host|docker> --infra=shared --name=NAME(also accepted byinstall.sh) makes a checkout
use another checkout's running MySQL, Elasticsearch, Kibana, Tika and Redis
instead of starting its own. NAME derives what must differ: database and user
tydal_NAME(test databasetydal_NAME_test), index prefixNAME_, Redis
prefixtydal_NAME_plus its own Redis DB numbers, session cookie, the
SPA's login-token cookie (VITE_AUTH_COOKIE, defaultJWT),
containerstydal_NAME_*(Compose projecttydal_NAME), and app/Vite ports
offset by 100·slot (--slot=N, else kept from the last run, else the lowest
free slot; a slot whose ports or Redis DBs another installation uses is
refused). The infrastructure services carry a Compose profile that
is empty (always on) by default and switched on only in shared mode; on the
docker tier the app services join the infrastructure stack's network.
Newtools/deploy/provision-shared.shcreates the database, test database
and user (idempotent,--dry-run);start.sh,test.sh,
first_install.sh(resets only that installation's database, indices and
Redis keys),install.shandreindex.shfollow the configured names via
tools/lib/stack.lib.sh. Container names and host ports in
docker-compose.ymlare now variables (TYDAL_STACK,TYDAL_HTTP_PORT, …)
whose defaults are the old literals, so--infra=own(the default) is
unchanged. Tests take a per-installation database and index prefix from
TYDAL_TEST_DB_DATABASE/TYDAL_TEST_INDEX_PREFIX(tests/bootstrap.php).
DEPLOYMENT.md: "Several installations on one server". -
--url=URLforconfigure.sh/install.sh: the public address of an
installation (own or shared) — writesAPP_URL,SANCTUM_STATEFUL_DOMAINS
and the SPA'sVITE_API_BASE_URL, and keeps it asTYDAL_PUBLIC_URLin
backend/.envso a later re-run no longer resets it tolocalhost;
--url=drops it. DEPLOYMENT.md: "The public URL". -
configure.sh --check, run byinstall.shbefore its prompt: validates
the flags, the slot and, in own mode, that no other checkout holds the
tydal_*container names (it names that checkout's folder) — instead of
failing halfway throughdocker compose up.--name=NAMEalone now
implies--infra=shared. -
install.shends with a summary of what it installed (installation, slot,
app and Vite URLs, public URL, database and index prefix, container status)
instead of letting it scroll away; composer and npm run quieter. -
ELASTICSEARCH_INDEX_PREFIX(#14): a per-installation prefix applied to
every physical index name — collection indices, their_chunks
companions andvault_<uuid>— through one helper,
ElasticsearchService::physicalIndexName().search_indexes.index_name
stays the logical, unprefixed name. Destructive commands only reach this
installation's prefix:search:wipe-indicesdeletes
{prefix}tydal_*,{prefix}vault_*(and warns when the prefix is empty),
search:setup-indices --recreateandsearch:reconcile --fixact on the
prefixed names. A prefix with wildcards, or one starting withtydal_/
vault_, is refused. Empty by default, so existing installations are
unchanged. In every backend env template, DEPLOYMENT.md
and CLI.md, with the
migration recipe for an existing installation. The test suite forces
test_, so it never touches a dev installation's indices. -
Archived page (#25): archived resources left every listing, search and
vault, and no page listed them, so once out of the basket they couldn't be
found again in the web app. NewGET /api/v1/resources/archived(MySQL, not
Elasticsearch) lists the current organization'sstate = archived
resources with the trash's rule — editors and viewers see their own,
administrators and owners see all — sorting (date, name, ID) and
pagination. The SPA's new Archived page (/archived, linked beside
Deleted resources) is modelled on the trash. Each card has Set live
and Move to trash icons; the page has Set all live (through
POST /resources/bulk/statein batches of up to 200) and Delete all
(moves them to the trash one by one, after a confirmation). Both report
skipped resources like the basket and leave them listed, and each control
shows only with its permission (resources.update/resources.delete).
User guide chapters 5 and 7. -
When a resource was archived (
resources.archived_at): stamped when a
resource moves toarchived(single update, bulk state, any save — the
model'ssavinghook, called explicitly by the quiet bulk write), cleared
when it leaves. Migration2026_10_06_000000_add_archived_at_to_resources
backfills existing archived rows fromupdated_at.GET /resources/archived
sorts byarchived_atby default (sort_byacceptsarchived_at,name,
id, and stillupdated_at), and the Archived page's cards read
"Archived ". -
aity:purge-batches: deletes AiTy Review batches reviewed (opened from
the AiTy Review page) or whose auto-approve job finished more than
AITY_BATCH_RETENTION_DAYS(default 30;0disables) days ago — the batch
workspace only, throughWorkspaceService::deleteWorkspace, never its
resources. Batches still waiting, running or being analysed are kept.
--days=N,--dry-run; scheduled daily at 04:00. docs/CLI.md. -
Required fields at the wizard's first step (#9). When the collection's
scheme has required metadata fields, step 1 shows a Required by this
collection panel and Next waits until they're filled; the values go into
every created resource and pre-fill Review. If every upload fails, the
Upload step shows the server's reason.
Changed
-
Editors can use the wizard's Auto option (#10). Auto opens an AiTy
Review batch (a workspace of purposeaity_review), which needed the
admin-onlyworkspaces.create; editors may now open those batches
(resources.createsuffices), while ordinary workspaces stay admin-only.
The wizard no longer swallows an Auto failure: it stays open with the
reason and reuses the batch already created on retry. -
Manage Workspaces leaves AiTy Review batches out. Every Auto upload
creates one, and the dialog listed them all under Managed by the system;
they have their own page (AiTy Review). Other system workspaces are still
listed. -
Consistent wording (#8, #12, #22). The resource view's legacy
Active/Visibility controls are gone and cards say Live / Draft / Archived;
the delete confirmation no longer says "cannot be undone" (resources go to
the trash); one short id (the tail of the UUID v7) on cards, trash and
basket; the vault key help namesingest/update/withdraw; the AiTy
Review empty state points to the wizard's Auto option; VAULT_SYSTEM.md §3
matches who creates vaults; categories are documented as API-only. -
install.sh/configure.shprint the full help when the tiers are
missing. -
Only administrators change what a vault shows. Adding resources to, or
removing them from, a workspace attached to a vault publishes or unpublishes
them outside TYDAL, so it now takes the new ability
workspaces.manage-vault-resources(admins and owners, viaworkspaces.*)
on top ofworkspaces.manage-resources. Enforced in
WorkspacePolicy::manageResources, so it covers the single add/remove
endpoints (resource editor chips, org-mcp tools) and the basket's
bulk-attach/detach, which report every id skipped asvault_connected.
Editors keep curating plain workspaces and AiTy Review batches; vault write
ops are unaffected.GET /workspacesnow returnsvaults_count, and the
basket's Workspace dialog and the resource editor's workspace chips show
vault-connected workspaces disabled ("Shared through a vault — ask an
administrator") to users without the ability. The basket's empty Workspace
list now says how to get one (ask an administrator, or Manage workspaces).
Fixed
-
Unbounded page size on the trash and Archived listings:
GET /resources/trashedandGET /resources/archivednow clamplimitto
1..200, the bulk endpoints' cap. -
Viewers could run AiTy auto-approve (#19).
POST /aity/auto-approve
and/aity/auto-approve/streamran for any member of the organization;
both now requiremanageResourceson a workspace of the current
organization (403, or 404 for another organization's), the stream before
it opens. -
The wizard's exit could fail silently or leave drafts (#20, #21). Keep
and Delete all report per-resource failures with Retry or Leave anyway;
they wait for the upload in flight ("Finishing uploads…") so a resource
created after the click isn't left as a draft for the hourly purge. Back →
Next with the same files retries only the failed rows; a resource whose
file upload fails is deleted again, so the counts match what exists. -
Editors were offered Save as workspace in the basket (#11), which they
can't do; it now shows only withworkspaces.create. -
Resources without a description couldn't be edited (#24). The built-in
schemes (multimedia, documents, general) requireddescription, but only
the edit form enforced it, so resources created by the wizard, FullFrame or
AI ingest, or the API — all without one — couldn't be saved or archived
from the form.descriptionis now optional in those schemes (seeder and a
migration for existing installations; the 10-character minimum still applies
when one is ...
TYDAL 1.3.0
Added
- User guide in
docs/user-guide/, for the
people who use TYDAL rather than run it: viewers, editors, administrators,
owners and platform admins. Nine chapters with screenshots: getting started,
finding resources, the upload wizard and AiTy suggestions, tags, the basket
and bulk actions, workspaces and vaults, the trash, organization settings
and platform administration. Its Known issues section links to the open
bugissues on GitHub. - Agent guide,
docs/AGENT_GUIDE.md, for AI agents
that use a TYDAL installation. It covers the three rings (installation;
organization, with AiTy and@tydal/org-mcp; vault, with
@tydal/vault-mcp), which one to use, how to connect, the tools, and rules
of conduct. AGENTS.mdfor AI coding agents working on this
repository: layout, tier-aware commands, tests, and the codebase's rules.TRUSTED_PROXIES(backend/config/trustedproxy.php): the IPs or CIDRs
of a TLS-terminating proxy to trust, or*for the direct peer. Behind a
host nginx, TYDAL saw plainhttpand builthttp://vault and file links;
with the proxy trusted, they'rehttps://. Empty by default, so
artisan serveand the docker dev tier are unchanged. In every backend env
template and in DEPLOYMENT.md.
Upgrading
- Behind a TLS-terminating proxy (a host nginx, a load balancer): set
TRUSTED_PROXIESinbackend/.envto the proxy's IPs or CIDRs, or to*
to trust the direct peer.*is safe only when the app's port is published
on127.0.0.1, so nothing but the proxy can reach it. The templates have
the variable, with a comment. Without a proxy, leave it empty. - Nothing else: no migrations, and the MCP packages and
@tydal/clientkeep
their 1.2.0 versions.
Full changes: v1.2.0...v1.3.0
TYDAL 1.2.0
Added
user:createandorg:create. Create a user (--email, optionally
--org=SLUG --role=…or--superadmin; the password is asked hidden, or
generated) and an organization (--name,--slug,--owner=EMAIL; the
owner must exist, and defaults to the oldest platform admin). See
CLI.md, "Users and organizations".- A vault reports its language.
/metacarrieslanguage, the ingest
target collection's language (null for a vault with no ingest target), so a
product can default to it (Full Frame's exhibition language).
@tydal/client1.6.0 types it. vault:reslug-files [--vault=SLUG] [--dry-run]brings existing file-link
slugs to the current rule. Run it after upgrading, or after changing
TYDAL_EXPORT_VISIBLE_FILENAMES.TYDAL_IMAGE_MAX_BYTESfor@tydal/vault-mcp(default 716800, about
700 KB).read_imagealways asks for theai-preparedrendition within this
budget, so a tool result fits Claude Desktop's 1 MB limit.
Changed
- Uploaded filenames no longer leave TYDAL. A vault's file links, the
public JSONfilenameand download names used to come from the uploaded
file's name, which can carry private details (a person's name, a date).
Now a file's slug is a 3-character code derived from the file and the
vault's salt, and downloads are named after the resource:
{resource-slug}-{code}.ext,{resource-slug}-{code}-{variant}.extfor a
rendition,{resource-slug}-preview.extfor a preview. Set
TYDAL_EXPORT_VISIBLE_FILENAMES=trueto keep the old behaviour. The
resource agent view and@tydal/org-mcp'sget_resourceno longer return
the fileslug. See VAULT_SYSTEM.md §4.3. mcp:tokenkeeps an existing member's role. Re-issuing a token used to
reset the machine user toeditor. Now a new member gets--role(default
editor), and an existing one keeps their role unless--roleis given,
which changes it and says so. Editors may only change resources they own: an
agent that edits other people's resources needs--role=admin.@tydal/org-mcp'supdate_resource_metadataanswers briefly: the
resource id, the fields updated with their saved values, andupdated_at,
instead of the whole resource.exhibitions:createasks for a new curator's password with the same
hidden, confirmed prompt asuser:create.- Brand. The SPA's default theme is now TYDAL, in the logo's blues
(primary#1A5D7D), with the new logo, the "ty" isotype as favicon, an
apple-touch-iconand a 512 px icon. The tagline is "the typed Digital Asset
Layer" throughout. SVG versions of the logos are in
frontend/src/assets/brand/. @tydal/vault-mcpand@tydal/org-mcpare now 1.1.0.
Fixed
- Vault link hashes could clash across vaults. A link's hash must be
unique across the installation, but each vault encodes with its own salt, so
two vaults could produce the same hash. Creating the link then failed. The
hash now grows by a character until it's free.
Upgrading
- Add
TYDAL_EXPORT_VISIBLE_FILENAMES=falsetobackend/.env(the
templates have it, with a comment). Leaving it out means the same. - Run
php artisan vault:reslug-files. Human file addresses change: a
/v/{org}/{vault}/{resource}/{file}address shared before the upgrade ends
in the old filename-based slug and stops resolving. Machine addresses
(/h/{vault}/{link}) and resource addresses are unchanged. - MCP clients: add
TYDAL_IMAGE_MAX_BYTESto the vault MCP's environment only
if you need a budget other than the default (seemcp.example.json).
Full changes: v1.1.0...v1.2.0
TYDAL 1.1.0
Added
- Purpose-agnostic vault write ops
ingest/update/withdraw.
Every purpose'singestnow lands in the vault's ingest target, and
galleryvaults gain all three next toactivate/open/close(curator
uploads for Full Frame). The payload is one flatmetadatadocument:
nameanddescriptiongo onto the resource, every other key into its
metadata.updateandwithdrawonly accept resources that vault's
ingestcreated; the write-info probe lists them (ingested) and reports
max_upload_bytes. See VAULT_WRITE_METHODS.md §3. exhibitions:setup/exhibitions:create: provision Full Frame photo
exhibitions.setupruns once per organization (photo scheme, index and
Photos collection);createruns once per exhibition (workspace, private
gallery vault, its read + write keys, and optionally a curator account).POST /api/v1/auth/identify: an identity check for products that use
TYDAL as their identity provider (Full Frame curators sign in with their
TYDAL account). No token or session is issued; rate-limited per email and
per IP.- Workspaces chosen by name when creating a vault. The vault form picks
the workspaces it reads from (workspace_idson vault create/update), and
the workspaces dialog manages the same links from the other side. tools/clients/fullframe.sh setup|create: a tier-aware front for
exhibitions:setup/exhibitions:create, so provisioning Full Frame
exhibitions no longer needsdocker exec -w /var/www/html ….exhibitions:setup --language=CODE: the Photos collection gets the
language you pick (asked interactively, defaulten), and a re-run with
the option corrects it. When run throughfullframe.sh, the closing hint
suggestsfullframe.sh createinstead ofphp artisan exhibitions:create.exhibitions:create --curator-password=…: a new curator's password
can be chosen instead of changed later. Interactive runs ask for it
(hidden, confirmed; empty = generated). It's validated before anything is
created, and an existing account's password is never overwritten.- Quick reference: every everyday script and
artisan command on one line, in docker and native form, with preconditions. - Tools index: what goes in each
tools/category. - The scheduler now runs in dev. Before, nothing ran
schedule:work, so
resource:prune,files:purge-uncommittedandresources:purge-draftsnever
fired. The docker tier gets aschedulercompose service (tydal_scheduler,
toggled with app/queue byconfigure.sh). On the host tierstart.shruns
schedule:workbeside the queue.start.shprints where the daemon runs and
warns if the container is down. DEPLOYMENT.md gains the production cron entry.
Changed
aivaultingestpayload.nameandsource_hashnow travel inside
themetadataJSON field instead of as top-level form fields, which are no
longer read.@tydal/client≥ 1.5.0 and@tydal/vault-mcpalready send the
new shape; raw multipart callers must update.- Login and registration are throttled per IP (20 and 10 a minute), on top
of the existing per-email limit on failed logins. tools/reorganized by role.deploy/keeps the stack lifecycle.
clients/holds what sits at TYDAL's border (vault-apps.sh, formerly
deploy/clients.sh, plusfullframe.sh).dev/holds seeding and smoke
(seed-vault.sh,loadtest.sh), andlib/the sourcedtier.lib.sh. The
root wrappers./clients.shand./seed-vault.shstill work.tools/deploy/test.shno longer resets the dev database. It used to run
migrate:fresh --seedontydalalthough Pest runs ontydal_test. It now
createstydal_testif missing, runs theclient/org-mcp/vault-mcp
suites (it pointed at the removedmcp/workspace), runs every suite even
after a failure, and accepts--backend-onlyand-- PEST_ARGS.
Fixed
- Uploads over 50 MB on the docker tier. The app image's nginx capped
every request body at 50 MB, below PHP's limits. Its body limit now matches
PHP_POST_MAX_SIZE(310 MB). seed-vault.shworks against the current API again. Resources are created
withstate: live, and the vault withorganization_id,state: publicand
workspace_ids. The removedvisibility/is_publishedfields made every
resource create fail and the vault come out private.vault-apps.shshieldsorg-mcp/andvault-mcp/node_modules
(it listed the removedmcp/).
Removed
tools/deploy/populate.sh,tools/deploy/query.shandtools/bulk_uploader/.
They had broken against the current API:visibilityinstead of the required
state, and calls to the removedextract/autotagendpoints. The uploader's
accept/tags logic already lives inAutoApprovalService. Use
tools/dev/seed-vault.shfor dev data (see tools/README.md).
TYDAL 1.0.0
TYDAL 1.0.0
First public release of TYDAL — the typed Digital Asset Layer.
The semantic layer between your files and your AI.
Schema-driven semantic vaults for AI agents.
From files to typed semantic resources.
TYDAL is a multi-tenant, schema-driven semantic knowledge system that structures, enriches, and projects digital resources through contextual Vaults.
Highlights
- Schema-driven resources with dynamic field contracts, validation, mappings, facets, and MIME rules.
- Contextual Vaults projecting Workspaces for delivery, galleries, Obsidian, AI, and mixed use cases.
- Semantic search and embeddings at resource and chunk level.
- Knowledge graph based on semantic tags and embedding similarity.
- AI-native Vault interface with grounded, citation-bearing Q&A.
- Two MCP surfaces for internal management and read-only Vault consumption.
- TypeScript client SDK shared across the SPA, MCP servers, and applications.
- Multi-tenant organization model with role- and permission-based access control.
- Elasticsearch indexing derived from the canonical MySQL data model.
- Docker-first development environment and deployment tooling.
This release establishes the public baseline for TYDAL. Internally, it incorporates the project's v2 architecture; as a publicly released product, this is TYDAL 1.0.0.
See CHANGELOG.md for the complete feature and change history.