Skip to content

Add the Multi-Tenant Catalogs Endpoint Extension, for nested catalog support#366

Draft
jonhealy1 wants to merge 22 commits intostac-utils:mainfrom
jonhealy1:stac-fastapi-catalogs-extension
Draft

Add the Multi-Tenant Catalogs Endpoint Extension, for nested catalog support#366
jonhealy1 wants to merge 22 commits intostac-utils:mainfrom
jonhealy1:stac-fastapi-catalogs-extension

Conversation

@jonhealy1
Copy link
Copy Markdown
Collaborator

@jonhealy1 jonhealy1 commented Mar 25, 2026

Related Issue(s):

Description:

Extension spec: https://github.com/StacLabs/multi-tenant-catalogs
STAC-FastAPI catalogs extension: https://github.com/StacLabs/stac-fastapi-catalogs-extension

  • extension routing /catalogs endpoint recognized
  • POST create Catalog
  • GET one Catalog by ID
  • GET all Catalogs
  • LINK sub-catalog
  • LINK sub-collection

How to Test

1. Start the Environment

Run the application using the updated compose file, which automatically enables the ENABLE_CATALOGS_ROUTE=TRUE environment variable.

docker compose up app

2. Manual API Testing

A. Create a Root Catalog

curl -X POST http://localhost:8082/catalogs \
  -H "Content-Type: application/json" \
  -d '{
    "id": "test-catalog-1",
    "type": "Catalog",
    "stac_version": "1.0.0",
    "description": "My first root catalog",
    "links": []
  }'

B. Get all Root Catalogs
(You should see test-catalog-1 returned in the catalogs array along with inferred self, parent, and root links)

curl -X GET http://localhost:8082/catalogs

C. Create a Sub-Catalog
Link a new sub-catalog specifically under test-catalog-1:

curl -X POST http://localhost:8082/catalogs/test-catalog-1/catalogs \
  -H "Content-Type: application/json" \
  -d '{
    "id": "my-sub-catalog",
    "type": "Catalog",
    "stac_version": "1.0.0",
    "description": "A nested sub-catalog",
    "links": []
  }'

D. List Sub-Catalogs
Fetch the children of test-catalog-1.
(You should see my-sub-catalog returned. Because the internal graph state is not exposed, you can verify the relationship was created successfully by checking the links array in the response, which will now contain a dynamically generated rel="parent" link pointing back to test-catalog-1):

curl -X GET http://localhost:8082/catalogs/test-catalog-1/catalogs

3. Run the Automated Tests

Run the newly added pytest suite specifically targeting the catalogs extension:

make test-catalogs

PR Checklist:

  • pre-commit hooks pass locally
  • Tests pass (run make test)
  • Documentation has been updated to reflect changes, if applicable, and docs build successfully (run make docs)
  • Changes are added to the CHANGELOG.

@jonhealy1
Copy link
Copy Markdown
Collaborator Author

It's going to be best to fix the extension so it supports python 3.11

@jonhealy1 jonhealy1 changed the title route extension, create, get catalogs Add the Multi-Tenant Virtual Catalogs Extension, for nested catalog support Mar 25, 2026
@jonhealy1 jonhealy1 changed the title Add the Multi-Tenant Virtual Catalogs Extension, for nested catalog support Add the Multi-Tenant Catalogs Endpoint Extension, for nested catalog support Mar 25, 2026
async with request.app.state.get_connection(request, "r") as conn:
logger.debug("Attempting to fetch all catalogs from database")
q, p = render(
"""
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than querying the collections table directly, you should build all of these on catalog_search. The tables in pgstac have no guarantee of stability if we need to modify the table structure when we are doing improvements while we try very hard to maintain the api contract for the search and collection_search functions. So, for this one, you should be able to do SELECT collection_search('{"filter":{"op":"=","args":[{"property":"type"},"Catalog"]},"limit":1}' (or close to that, I didn't actually check that query). I think you should be able to do everything you want with CQL2 array operators, if there is any pgstac/cql2 functionality that might be missing I can make a priority to get it added into pgstac.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - really good to know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants