Skip to content

Releases: eonity-org/tydal

TYDAL 1.5.0

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 10:32
f4c734d

Added

  • AITY suggestions at the vault write boundary. A gallery ingest with
    suggest: true runs 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 may update; reading never
    starts AITY.
    @tydal/client gets suggestions(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

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 08:02

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 on 127.0.0.1, data on a data disk) and, per
    installation, a compose file, a make-env.sh that writes the production
    backend/.env and creates the database, and an nginx site. With
    ELASTICSEARCH_INDEX_PREFIX and 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 of exhibitions: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

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 08:02

Added

  • Several installations on one server (#23): configure.sh <ai> <host|docker> --infra=shared --name=NAME (also accepted by install.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 database tydal_NAME_test), index prefix NAME_, Redis
    prefix tydal_NAME_ plus its own Redis DB numbers, session cookie, the
    SPA's login-token cookie (VITE_AUTH_COOKIE, default JWT),
    containers tydal_NAME_* (Compose project tydal_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.
    New tools/deploy/provision-shared.sh creates 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.sh and reindex.sh follow the configured names via
    tools/lib/stack.lib.sh. Container names and host ports in
    docker-compose.yml are 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=URL for configure.sh / install.sh: the public address of an
    installation (own or shared) — writes APP_URL, SANCTUM_STATEFUL_DOMAINS
    and the SPA's VITE_API_BASE_URL, and keeps it as TYDAL_PUBLIC_URL in
    backend/.env so a later re-run no longer resets it to localhost;
    --url= drops it. DEPLOYMENT.md: "The public URL".

  • configure.sh --check, run by install.sh before 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 through docker compose up. --name=NAME alone now
    implies --infra=shared.

  • install.sh ends 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 and vault_<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-indices deletes
    {prefix}tydal_*,{prefix}vault_* (and warns when the prefix is empty),
    search:setup-indices --recreate and search:reconcile --fix act on the
    prefixed names. A prefix with wildcards, or one starting with tydal_ /
    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. New GET /api/v1/resources/archived (MySQL, not
    Elasticsearch) lists the current organization's state = 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/state in 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 to archived (single update, bulk state, any save — the
    model's saving hook, called explicitly by the quiet bulk write), cleared
    when it leaves. Migration 2026_10_06_000000_add_archived_at_to_resources
    backfills existing archived rows from updated_at. GET /resources/archived
    sorts by archived_at by default (sort_by accepts archived_at, name,
    id, and still updated_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; 0 disables) days ago — the batch
    workspace only, through WorkspaceService::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 purpose aity_review), which needed the
    admin-only workspaces.create; editors may now open those batches
    (resources.create suffices), 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 names ingest / 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.sh print 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, via workspaces.*)
    on top of workspaces.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 as vault_connected.
    Editors keep curating plain workspaces and AiTy Review batches; vault write
    ops are unaffected. GET /workspaces now returns vaults_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/trashed and GET /resources/archived now clamp limit to
    1..200, the bulk endpoints' cap.

  • Viewers could run AiTy auto-approve (#19). POST /aity/auto-approve
    and /aity/auto-approve/stream ran for any member of the organization;
    both now require manageResources on 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 with workspaces.create.

  • Resources without a description couldn't be edited (#24). The built-in
    schemes (multimedia, documents, general) required description, 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. description is now optional in those schemes (seeder and a
    migration for existing installations; the 10-character minimum still applies
    when one is ...

Read more

TYDAL 1.3.0

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 08:02

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
    bug issues 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.md for 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 plain http and built http:// vault and file links;
    with the proxy trusted, they're https://. Empty by default, so
    artisan serve and the docker dev tier are unchanged. In every backend env
    template and in DEPLOYMENT.md.

Upgrading

  1. Behind a TLS-terminating proxy (a host nginx, a load balancer): set
    TRUSTED_PROXIES in backend/.env to the proxy's IPs or CIDRs, or to *
    to trust the direct peer. * is safe only when the app's port is published
    on 127.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.
  2. Nothing else: no migrations, and the MCP packages and @tydal/client keep
    their 1.2.0 versions.

Full changes: v1.2.0...v1.3.0

TYDAL 1.2.0

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 08:01

Added

  • user:create and org: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. /meta carries language, 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/client 1.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_BYTES for @tydal/vault-mcp (default 716800, about
    700 KB). read_image always asks for the ai-prepared rendition 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 JSON filename and 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}.ext for a
    rendition, {resource-slug}-preview.ext for a preview. Set
    TYDAL_EXPORT_VISIBLE_FILENAMES=true to keep the old behaviour. The
    resource agent view and @tydal/org-mcp's get_resource no longer return
    the file slug. See VAULT_SYSTEM.md §4.3.
  • mcp:token keeps an existing member's role. Re-issuing a token used to
    reset the machine user to editor. Now a new member gets --role (default
    editor), and an existing one keeps their role unless --role is 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's update_resource_metadata answers briefly: the
    resource id, the fields updated with their saved values, and updated_at,
    instead of the whole resource.
  • exhibitions:create asks for a new curator's password with the same
    hidden, confirmed prompt as user: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-icon and 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-mcp and @tydal/org-mcp are 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

  1. Add TYDAL_EXPORT_VISIBLE_FILENAMES=false to backend/.env (the
    templates have it, with a comment). Leaving it out means the same.
  2. 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.
  3. MCP clients: add TYDAL_IMAGE_MAX_BYTES to the vault MCP's environment only
    if you need a budget other than the default (see mcp.example.json).

Full changes: v1.1.0...v1.2.0

TYDAL 1.1.0

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 07:59

Added

  • Purpose-agnostic vault write ops ingest / update / withdraw.
    Every purpose's ingest now lands in the vault's ingest target, and
    gallery vaults gain all three next to activate/open/close (curator
    uploads for Full Frame). The payload is one flat metadata document:
    name and description go onto the resource, every other key into its
    metadata. update and withdraw only accept resources that vault's
    ingest created; 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. setup runs once per organization (photo scheme, index and
    Photos collection); create runs 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_ids on 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 needs docker exec -w /var/www/html ….
  • exhibitions:setup --language=CODE: the Photos collection gets the
    language you pick (asked interactively, default en), and a re-run with
    the option corrects it. When run through fullframe.sh, the closing hint
    suggests fullframe.sh create instead of php 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-uncommitted and resources:purge-drafts never
    fired. The docker tier gets a scheduler compose service (tydal_scheduler,
    toggled with app/queue by configure.sh). On the host tier start.sh runs
    schedule:work beside the queue. start.sh prints where the daemon runs and
    warns if the container is down. DEPLOYMENT.md gains the production cron entry.

Changed

  • ai vault ingest payload. name and source_hash now travel inside
    the metadata JSON field instead of as top-level form fields, which are no
    longer read. @tydal/client ≥ 1.5.0 and @tydal/vault-mcp already 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, plus fullframe.sh). dev/ holds seeding and smoke
    (seed-vault.sh, loadtest.sh), and lib/ the sourced tier.lib.sh. The
    root wrappers ./clients.sh and ./seed-vault.sh still work.
  • tools/deploy/test.sh no longer resets the dev database. It used to run
    migrate:fresh --seed on tydal although Pest runs on tydal_test. It now
    creates tydal_test if missing, runs the client/org-mcp/vault-mcp
    suites (it pointed at the removed mcp/ workspace), runs every suite even
    after a failure, and accepts --backend-only and -- 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.sh works against the current API again. Resources are created
    with state: live, and the vault with organization_id, state: public and
    workspace_ids. The removed visibility / is_published fields made every
    resource create fail and the vault come out private.
  • vault-apps.sh shields org-mcp/ and vault-mcp/ node_modules
    (it listed the removed mcp/).

Removed

  • tools/deploy/populate.sh, tools/deploy/query.sh and tools/bulk_uploader/.
    They had broken against the current API: visibility instead of the required
    state, and calls to the removed extract/autotag endpoints. The uploader's
    accept/tags logic already lives in AutoApprovalService. Use
    tools/dev/seed-vault.sh for dev data (see tools/README.md).

TYDAL 1.0.0

Choose a tag to compare

@tydaleon tydaleon released this 08 Oct 07:59

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.