From 7472474edc62ded650514a00feaa098b81fc2090 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Tue, 20 Apr 2021 09:22:58 -0400 Subject: [PATCH 1/6] Remove stac-spec git submodule --- .gitmodules | 3 --- stac-spec | 1 - 2 files changed, 4 deletions(-) delete mode 100644 .gitmodules delete mode 160000 stac-spec diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index b301bd95..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "stac-spec"] - path = stac-spec - url = https://github.com/radiantearth/stac-spec diff --git a/stac-spec b/stac-spec deleted file mode 160000 index 4988a40f..00000000 --- a/stac-spec +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4988a40f6071666d345e4a1c5adc9a6338973769 From b544f2dcf63bd067548b369b95fb9afa4535a0bc Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Tue, 20 Apr 2021 09:33:48 -0400 Subject: [PATCH 2/6] Squashed 'stac-spec/' content from commit ebd16753 git-subtree-dir: stac-spec git-subtree-split: ebd167536b17d3e311dd6a3fd963799db3f5fb28 --- .circleci/config.yml | 53 ++ .circleci/publish-schemas.js | 40 + .circleci/rc.yaml | 46 ++ .github/pull_request_template.md | 14 + .gitignore | 69 ++ .remarkignore | 1 + CHANGELOG.md | 420 +++++++++++ CODE_OF_CONDUCT.md | 76 ++ CONTRIBUTING.md | 81 ++ LICENSE | 201 +++++ README.md | 109 +++ STAC-UML.drawio | 1 + STAC-UML.pdf | Bin 0 -> 46890 bytes best-practices.md | 709 ++++++++++++++++++ catalog-spec/README.md | 34 + catalog-spec/catalog-spec.md | 127 ++++ catalog-spec/json-schema/catalog-core.json | 139 ++++ catalog-spec/json-schema/catalog.json | 29 + collection-spec/README.md | 43 ++ collection-spec/collection-spec.md | 260 +++++++ collection-spec/json-schema/collection.json | 170 +++++ examples/README.md | 89 +++ examples/catalog.json | 30 + examples/collection-only/collection.json | 228 ++++++ examples/collection.json | 93 +++ examples/collectionless-item.json | 147 ++++ examples/core-item.json | 117 +++ examples/extended-item.json | 191 +++++ .../extensions-collection/collection.json | 66 ++ .../proj-example/proj-example.json | 278 +++++++ examples/simple-item.json | 74 ++ extensions/README.md | 172 +++++ item-spec/README.md | 23 + item-spec/common-metadata.md | 186 +++++ item-spec/item-spec.md | 306 ++++++++ item-spec/json-schema/basics.json | 18 + item-spec/json-schema/datetime.json | 48 ++ item-spec/json-schema/instrument.json | 32 + item-spec/json-schema/item.json | 250 ++++++ item-spec/json-schema/licensing.json | 12 + item-spec/json-schema/provider.json | 47 ++ overview.md | 186 +++++ package.json | 26 + principles.md | 45 ++ process.md | 119 +++ schema.json | 0 46 files changed, 5405 insertions(+) create mode 100644 .circleci/config.yml create mode 100644 .circleci/publish-schemas.js create mode 100644 .circleci/rc.yaml create mode 100644 .github/pull_request_template.md create mode 100644 .gitignore create mode 100644 .remarkignore create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 STAC-UML.drawio create mode 100644 STAC-UML.pdf create mode 100644 best-practices.md create mode 100644 catalog-spec/README.md create mode 100644 catalog-spec/catalog-spec.md create mode 100644 catalog-spec/json-schema/catalog-core.json create mode 100644 catalog-spec/json-schema/catalog.json create mode 100644 collection-spec/README.md create mode 100644 collection-spec/collection-spec.md create mode 100644 collection-spec/json-schema/collection.json create mode 100644 examples/README.md create mode 100644 examples/catalog.json create mode 100644 examples/collection-only/collection.json create mode 100644 examples/collection.json create mode 100644 examples/collectionless-item.json create mode 100644 examples/core-item.json create mode 100644 examples/extended-item.json create mode 100644 examples/extensions-collection/collection.json create mode 100644 examples/extensions-collection/proj-example/proj-example.json create mode 100644 examples/simple-item.json create mode 100644 extensions/README.md create mode 100644 item-spec/README.md create mode 100644 item-spec/common-metadata.md create mode 100644 item-spec/item-spec.md create mode 100644 item-spec/json-schema/basics.json create mode 100644 item-spec/json-schema/datetime.json create mode 100644 item-spec/json-schema/instrument.json create mode 100644 item-spec/json-schema/item.json create mode 100644 item-spec/json-schema/licensing.json create mode 100644 item-spec/json-schema/provider.json create mode 100644 overview.md create mode 100644 package.json create mode 100644 principles.md create mode 100644 process.md create mode 100644 schema.json diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..7095d1c8 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,53 @@ +version: 2 +jobs: + test_examples: + working_directory: ~/stac + docker: + - image: circleci/node:12 + steps: + - checkout + - run: + name: install + command: npm install + - run: + name: validate + command: npm run check-examples + test_docs: + working_directory: ~/stac + docker: + - image: circleci/node:12 + steps: + - checkout + - run: + name: install + command: npm install + - run: + name: validate + command: npm run check-markdown + publish_schemas: + working_directory: ~/stac + docker: + - image: circleci/node:12 + steps: + - checkout + - run: + name: install + command: npm install + - add_ssh_keys: + fingerprints: + - "9b:0a:88:ff:12:d1:29:9a:ff:bb:72:ab:7d:81:df:59" + - run: + name: publish + command: npm run publish-schemas -- $CIRCLE_TAG +workflows: + version: 2 + ci: + jobs: + - test_examples + - test_docs + - publish_schemas: + filters: + tags: + only: /^v.*/ + branches: + ignore: /^((?!dev).)*$/ \ No newline at end of file diff --git a/.circleci/publish-schemas.js b/.circleci/publish-schemas.js new file mode 100644 index 00000000..824f88c2 --- /dev/null +++ b/.circleci/publish-schemas.js @@ -0,0 +1,40 @@ +const klaw = require('klaw-sync'); +const path = require('path'); +const fs = require('fs'); +const ghpages = require('gh-pages'); + +function filterFn (item) { + const basename = path.basename(item.path); + return basename === '.' || basename === 'node_modules' || basename[0] !== '.'; +} + +let args = process.argv.slice(2); +let tag = 'dev'; +if (args.length && args[0].trim().length > 0) { + tag = args[0]; +} + +var folder = '.'; +var jsonSchemaFolderPattern = path.sep + 'json-schema' + path.sep; +for (let file of klaw(folder, {filter: filterFn})) { + if (file.path.includes(jsonSchemaFolderPattern) && path.extname(file.path) === '.json') { + let source = file.path; + let target = 'schemas' + path.sep + tag + path.sep + path.relative(folder, file.path); + fs.mkdirSync(path.dirname(target), { recursive: true }); + fs.copyFileSync(source, target); + console.log(target); + } +} + +ghpages.publish('schemas/' + tag, { + src: '**', + dest: tag, + message: 'Publish JSON Schemas [ci skip]', + user: { + name: 'STAC CI', + email: 'ci@stacspec.org' + } +}, error => { + console.error(error ? error : 'Deployed to gh-pages'); + process.exit(error ? 1 : 0); +}); \ No newline at end of file diff --git a/.circleci/rc.yaml b/.circleci/rc.yaml new file mode 100644 index 00000000..625a856a --- /dev/null +++ b/.circleci/rc.yaml @@ -0,0 +1,46 @@ +plugins: +# Check links + - validate-links +# Apply some recommended defaults for consistency + - remark-preset-lint-consistent + - remark-preset-lint-recommended +# No HTML for security - can't activate yet due to STAC logo in README.md +# - lint-no-html +# General formatting +# - - remark-lint-emphasis-marker +# - '*' + - remark-lint-hard-break-spaces + - remark-lint-blockquote-indentation + - remark-lint-no-consecutive-blank-lines +# Detect overly long lines - be liberal for now and don't restrict to 80 yet +# - - remark-lint-maximum-line-length +# - 150 +# Code + - remark-lint-fenced-code-flag + - remark-lint-fenced-code-marker + - remark-lint-no-shell-dollars + - - remark-lint-code-block-style + - 'fenced' +# Headings + - remark-lint-heading-increment + - remark-lint-no-duplicate-headings + - remark-lint-no-multiple-toplevel-headings + - remark-lint-no-heading-punctuation + - - remark-lint-maximum-heading-length + - 70 + - - remark-lint-heading-style + - atx +# Lists + - remark-lint-list-item-bullet-indent + - remark-lint-ordered-list-marker-style + - remark-lint-ordered-list-marker-value + - remark-lint-checkbox-character-style +# - - remark-lint-unordered-list-marker-style +# - '-' + - - remark-lint-list-item-indent + - space +# Tables + - remark-lint-table-pipes +# - remark-lint-table-pipe-alignment # Wait for https://github.com/remarkjs/remark-lint/issues/226 +# Urls + - remark-lint-no-literal-urls \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..e26fc2c9 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,14 @@ +**Related Issue(s):** # + + +**Proposed Changes:** + +1. +2. + +**PR Checklist:** + +- [ ] This PR is made against the dev branch (all proposed changes except releases should be against dev, not master). +- [ ] This PR has **no** breaking changes. +- [ ] I have added my changes to the [CHANGELOG](https://github.com/radiantearth/stac-spec/blob/dev/CHANGELOG.md) **or** a CHANGELOG entry is not required. +- [ ] This PR affects the [STAC API spec](https://github.com/radiantearth/stac-api-spec), and I have opened issue/PR #XXX to track the change. diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ab3dafa3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,69 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ +package-lock.json + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# IntelliJ IDEA files +.idea/ +*.iml + +# Folder created when CI puhlishes JSON Schemas +schemas/ diff --git a/.remarkignore b/.remarkignore new file mode 100644 index 00000000..32524460 --- /dev/null +++ b/.remarkignore @@ -0,0 +1 @@ +/CHANGELOG.md \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..9a8027a1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,420 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [v1.0.0-rc.2] - 2021-03-30 + +### Changed + +- Required properties of type `string` require a minimum length of `1`. ([#1065](https://github.com/radiantearth/stac-spec/pull/1065)) +- `gsd` must be greater than 0. ([#1068](https://github.com/radiantearth/stac-spec/pull/1068)) + +### Removed + +- The remaining extensions in the spec (EO, Projection, Scientific Citation and View) have been moved out of the core specification, into their own repos in the [stac-extensions](https://github.com/stac-extensions/) GitHub organization. They must now be referred to by their schemas directly - the name shortcuts for them are no longer valid. The concept of the 'named shortcut' also goes away entirely. ([#1070](https://github.com/radiantearth/stac-spec/pull/1070)) + +### Fixed + +- Collection Assets were specified as required (only in written text, not in JSON Schema), but that was incorrectly copied over from the former `collection-assets` extension. Collection Assets are not required. +- Clarified that the values in summaries (both for ranges and sets of values) must follow the data type of the property they summarize. ([#1069](https://github.com/radiantearth/stac-spec/pull/1069)) + +## [v1.0.0-rc.1] - 2021-03-03 + +### Added + +- Catalog and Collection now require a `type` parameter, to be set to `Catalog` or `Collection` for clients to more easily distinguish them easily. ([#971](https://github.com/radiantearth/stac-spec/pull/971)) +- Collection specification adds Assets (previously needed Collections Asset extension to do that). ([#1008](https://github.com/radiantearth/stac-spec/pull/1008)) +- 'via' and 'canonical' rel types are now options in Items. ([#884](https://github.com/radiantearth/stac-spec/pull/884)) +- In Extensions list there is now reference to three new (non-core) extensions: [processing](https://github.com/stac-extensions/processing), [file info](https://github.com/stac-extensions/file) and [card4l](https://github.com/stac-extensions/card4l). These would have been added to the stac-spec repo, except all non-core extensions were moved to [stac-extensions](https://github.com/stac-extensions/) org. ([#1024](https://github.com/radiantearth/stac-spec/pull/1024)) +- 'summaries' are now available in the Catalog spec, so both catalogs and collections can make use of it. ([#903](https://github.com/radiantearth/stac-spec/issues/903)) +- There is a new recommendation to enable CORS. ([#940](https://github.com/radiantearth/stac-spec/pull/940)) +- A Best Practice section on 'requester pays' cloud buckets was added. ([#1021](https://github.com/radiantearth/stac-spec/pull/1021)) +- A new Best Practice section explains Asset Roles, plus some lists of potential roles for people to use (in best practices, sar and eo). ([#989](https://github.com/radiantearth/stac-spec/pull/989)) +- There is a new Best Practice recommendation to keep collections at consistent levels. ([#1009](https://github.com/radiantearth/stac-spec/pull/1009)) + +### Changed + +- The [Stats Object](collection-spec/collection-spec.md#stats-object) for Collection `summaries` changed `min` to `minimum` and `max` to `maximum` to align with JSON Schema. ([#967](https://github.com/radiantearth/stac-spec/pull/967)) +- URIs (usually found int properties like `href`, `url`) are now validated using the `iri-reference` format in JSON Schema (allows international characters in URIs) ([#953](https://github.com/radiantearth/stac-spec/pull/953)) +- Enhanced the way the spec talks about ID's to encourage more global uniqueness. ([#883](https://github.com/radiantearth/stac-spec/pull/883)) +- Clarified how collection-level asset object properties do not remove the need for item-level asset object properties in the `item-assets` extension ([#880](https://github.com/radiantearth/stac-spec/pull/880)) +- Made `summaries` to be *strongly recommended* - everyone should strive to implement them, as they are very useful. ([#985](https://github.com/radiantearth/stac-spec/pull/985)) +- Moved examples from individual directories into a single /examples folder at the root, and evolved them to be more representative. ([#955](https://github.com/radiantearth/stac-spec/pull/955)) +- Renamed "Scientific Extension" to "Scientific Citation Extension" ([#990](https://github.com/radiantearth/stac-spec/issues/990)) +- Relaxed the regular expression for DOIs in the scientific extension ([#910](https://github.com/radiantearth/stac-spec/issues/910)) +- `proj:geometry` allows all GeoJSON geometries instead of just a polygon. ([#995](https://github.com/radiantearth/stac-spec/pull/995)) + +### Removed + +- Checksum extension (field `checksum:multihash`). Use File Info extension (field `file:checksum`) instead for assets. There's no replacement for links. ([#934](https://github.com/radiantearth/stac-spec/pull/934)) +- Collection Assets extension, as the core construct of Assets in a Collection is now part of the core Collection spec. No change is required except removing `collection-assets` from the list of `stac_extensions`. ([#1008](https://github.com/radiantearth/stac-spec/pull/1008)) +- Numerous extensions (Data Cube, Item Assets, Point Cloud, SAR, Single File STAC, Tiled Assets, Timestamps & Versioning) have been moved out of the core specification, into their own repos in the [stac-extensions](https://github.com/stac-extensions/) GitHub organization. They must now be referred to by their schemas directly - the name shortcuts for them are no longer valid. ([#1024](https://github.com/radiantearth/stac-spec/pull/1024)) + +### Fixed + +- Fixed JSON Schema for `providers` (Collections and Items) to be an object and require a `name`. ([#924](https://github.com/radiantearth/stac-spec/pull/924)) + +## [v1.0.0-beta.2] - 2020-07-08 + +### Added +- JSON-schema file in the Point Cloud extension. + +### Changed +- Clarification on null geometries, making bbox not required if a null geometry is used. +- Multiple extents (bounding boxes / intervals) are allowed per Collection +- In the scientific extension, a link with the rel-type 'cite-as' SHOULD be used for the main publication of the dataset (the same as the one described in `sci:doi`), and not for the DOIs referenced in the `sci:publications` property. + +### Removed +- Validation instructions + +### Fixed +- Fixed several JSON Schemas +- Fixed examples + +## [v1.0.0-beta.1] - 2020-05-29 + +### Removed +- The API portion of STAC has been split off into a [new repository: stac-api-spec](https://github.com/radiantearth/stac-api-spec) and will start being versioned and released separately than the core STAC spec. +- proj4 string from proj extension +- Various warnings about how the spec is very early and likely will change. +- implementations.md (migrated to https://stacspec.org) and how-to-help.md (migrated to https://github.com/stac-utils/stac-ecosystem). +- `commons` extension completely removed: Items should contain all properties and not default to a common set at the Collection level +- ItemCollection removed from stac-spec core repo, will migrate to [stac-api-spec](https://github.com/radiantearth/stac-api-spec) as that is the only place it is used. + +### Added +- 'alternate' as a listed 'rel' type with recommended 'text/html' to communicate there is an html version. +- Added a code of conduct based on github's template. +- Overview document that gives a more explanatory discussion of the various parts of the spec and how they relate +- Several new sections to 'best practices' document. +- Added the ability to define Item properties under Assets (item-spec/item-spec.md) +- Add `proj:shape` and `proj:transform` to the projections extension. +- Collection-level assets extension +- Instructions on how to run check-markdown locally +- Timestamps extensions (adds fields `published`, `expires` and `unpublished`) +- `created` and `updated` can be used in the assets to specify the creation / update times of the assets. +- [Tiled Assets extension](extensions/tiled-assets/README.md), for representing data that has been split into tiles + +### Changed +- [Label extension](extensions/label/README.md) types were clarified and types in README and JSON schema were brought into alignment +- Moved item recommendations to best practices, and added a bit more in item spec about 'search' +- Moved `eo:gsd` from `eo` extension to core `gsd` field in Item common metadata +- `asset` extension renamed to `item-assets` and renamed `assets` field in Collections to `item_assets` +- `item-assets` extension only requires any two fields to be available, not the two specific fields `title` and `type` +- `datetime` allows `null` as value, but requires `start_datetime` and `end_datetime` then +- Extensions `sat`, `scientific` and `view`: At least one field is required to be specified. +- [Single File STAC extension](extensions/single-file-stac/README.md) changed to be a complete STAC catalog + GeoJSON FeatureCollection that contains collections and items. +- Improved several JSON Schemas + +### Fixed +- Datacube extension: `cube:dimensions` was not flagged as required. + +## [v0.9.0] - 2020-02-26 + +### Added +- ItemCollection requires `stac_version` field, `stac_extensions` has also been added +- A `description` field has been added to Item assets (also Asset definitions extension) +- Field `mission` to [Common Metadata fields](item-spec/common-metadata.md) +- Extensions: + - [Version Indicators extension](extensions/version/README.md), new `version` and `deprecated` fields in STAC Items and Collections + - Data Cube extension can be used in Collections, added new field `description` + - [Asset Extension](extensions/asset/README.md): new `description` and `roles` fields + - New [Projection Extension](extensions/projection/README.md) to describe Items with Assets that have an associated geospatial projection + - New [View Geometry Extension](extensions/view/README.md) +- STAC API: + - Added the [Item and Collection API Version extension](https://github.com/radiantearth/stac-api-spec/tree/master/extensions/version/README.md) to support versioning in the API specification + - Run `npm run serve` or `npm run serve-ext` to quickly render development versions of the OpenAPI spec in the browser +- [Basics](item-spec/common-metadata.md#basics) added to Common Metadata definitions with new `description` field for +Item properties +- New fields to the `link` object to facilitate [pagination support for POST requests](https://github.com/radiantearth/stac-api-spec/tree/master/api-spec.md#paging-extension) +- `data` role, as a suggestion for a common role for data files to be used in case data providers don't come up with their own names and semantics +- Clarification text on HTTP verbs in STAC API + +### Changed +- Support for [CommonMark 0.29 instead of CommonMark 0.28](https://spec.commonmark.org/0.29/changes.html) +- Collection field `property` and the merge ability moved to a new extension 'Commons' +- Added field `roles` to Item assets (also Asset definitions extension), to be used similarly to Link `rel` +- Updated API yaml to clarify bbox filter should be implemented without brackets. Example: `bbox=160.6,-55.95,-170,-25.89` +- Collection `summaries` merge array fields now +- Several fields have been moved from extensions or item fields to the [Common Metadata fields](item-spec/common-metadata.md): + - `eo:platform` / `sar:platform` => `platform` + - `eo:instrument` / `sar:instrument` => `instruments`, also changed from string to array of strings + - `eo:constellation` / `sar:constellation` => `constellation` + - `dtr:start_datetime` => `start_datetime` + - `dtr:end_datetime` => `end_datetime` +- Moved angle definitions from extensions `eo` and new `view` extension + - `eo:off_nadir` -> `view:off_nadir` + - `eo:azimuth` -> `view:azimuth` + - `eo:incidence_angle` -> `view:incidence_angle` + - `eo:sun_azimuth` -> `view:sun_azimuth` + - `eo:sun_elevation` -> `view:sun_elevation` +- Extensions: + - Data Cube extension: Changed allowed formats (removed PROJ string, added PROJJSON / WKT2) for reference systems + - [Checksum extension](extensions/checksum/README.md) is now using self-identifiable hashes ([Multihash](https://github.com/multiformats/multihash)) + - Changed `sar:type` to `sar:product_type` and `sar:polarization` to `sar:polarizations` in the [SAR extension](extensions/sar/README.md) +- STAC API: + - The endpoint `/stac` has been merged with `/` + - The endpoint `/stac/search` is now called `/search` + - Sort Extension - added non-JSON query/form parameter format + - Fields extension has a simplified format for GET parameters + - `search` extension renamed to `context` extension. JSON object renamed from `search:metadata` to `context` + - Removed "next" from the search metadata and query parameter, added POST body and headers to the links for paging support + - Query Extension - type restrictions on query predicates are more accurate, which may require additional implementation support +- Item `title` definition moved from core Item fields to [Common Metadata Basics](item-spec/common-metadata.md#basics) +fields. No change is required for STAC Items. +- `putFeature` can return a `PreconditionFailed` to provide more explicit information when the resource has changed in the server +- [Sort extension](https://github.com/radiantearth/stac-api-spec/tree/master/extensions/sort) now uses "+" and "-" prefixes for GET requests to denote sort order. +- Clarified how `/search` links must be added to `/` and changed that links to both GET and POST must be provided now that the method can be specified in links + +### Removed +- `version` field in STAC Collections. Use [Version Extension](extensions/version/README.md) instead +- `summaries` field from Catalogs. Use Collections instead +- Asset Types (pre-defined values for the keys of individual assets, *not* media types) in Items. Use the asset's `roles` instead +- `license` field doesn't allow SPDX expressions any longer. Use `various` and links instead +- Extensions: + - `eo:platform`, `eo:instrument`, `eo:constellation` from EO extension, and `sar:platform`, `sar:instrument`, `sar:constellation` from the [SAR extension](extensions/sar/README.md) + - Removed from EO extension field `eo:epsg` in favor of `proj:epsg` + - `gsd` and `accuracy` from `eo:bands` in the [EO extension](extensions/eo/README.md) + - `sar:absolute_orbit` and `sar:center_wavelength` fields from the [SAR extension](extensions/sar/README.md) + - `data_type` and `unit` from the `sar:bands` object in the [SAR extension](extensions/sar/README.md) + - Datetime Range (`dtr`) extension. Use the [Common Metadata fields](item-spec/common-metadata.md) instead +- STAC API: + - `next` from the search metadata and query parameter +- In API, removed any mention of using media type `multipart/form-data` and `x-www-form-urlencoded` + +### Fixed + +- The `license` field in Item and Collection spec explicitly mentions that the value `proprietary` without a link means that the data is private +- Clarified how to fill `stac_extensions` +- More clarifications; typos fixed +- Fixed Item JSON Schema now `allOf` optional Common Metadata properties are evaluated +- Clarified usage of optional Common Metadata fields for STAC Items +- Clarified usage of paging options, especially in relation to what OGC API - Features offers +- Allow Commonmark in asset description, as it's allowed everywhere else +- Put asset description in the API +- Fixed API spec regarding license expressions +- Added missing schema in the API Version extension +- Fixed links in the Landsat example in the collection-spec + +## [v0.8.1] - 2019-11-01 + +### Changed +- Updated specification to base on OGC API - Features - Part 1: Core, v1.0.0 instead of OGC API - Features - Part 1: Core, v1.0.0-draft.2 (fka WFS3 draft 2). + +### Fixed +- Numerous typos, clarifications and fixes for documentation and examples. +- Fixed STAC API definition to include STAC-related fields and examples in *OGC API - Features*-derived endpoints. +- Fixed JSON schemas for extensions: `$id` field matches file name. + +## [v0.8.0] - 2019-10-11 + +### Changed +- Updated specification to base on WFS3 draft 2 (OGC API - Features - Part 1: Core, v1.0.0-draft.2). This leads to many changes in the API and one change in STAC collections, notably: + - The structure of the field `extent` in STAC and WFS Collections changed. + - Query parameter `time` was renamed to `datetime` and accepts slightly different values. + - WFS links have additional fields `hreflang` and `length`. + - WFS Collections have additional fields `crs` and `itemType`. + - `time` API parameter changed to `datetime` +- The API intersects parameter now accepts a GeoJSON Geometry (any type) *instead* of a GeoJSON Feature. +- API: Clarification on `include` and `exclude` parameters in the field extension and notes on default values. +- API: queries should contain either `bbox` or `intersects`. +- API: Core API now has reserved parameters to prevent overlap with extensions +- Updated bbox definitions in API, Item, and Collection specs to include support for optional elevation values. +- Moved Single Item Extension to core (`license` and `providers` properties for Items). +- Allow `various` for the `license` fields. +- Clarified meaning of SAR and EO platform, constellation, and instrument +- Numerous typos, clarification and general word-smithing +- Changed GeoTIFF media type from `image/vnd.stac.geotiff` to `image/tiff; application=geotiff`, changed Cloud-optimized GeoTiff media type from `image/vnd.stac.geotiff; cloud-optimized=true` to `image/tiff; application=geotiff; profile=cloud-optimized`. + +### Added +- **stac_version**: Each Item must specify the STAC version. +- **stac_extensions**: Introduced this field for Items, Catalogs and Collections. +- Property `summaries` have been added to catalogs and collections. +- API Transaction extension supports optimistic locking through use of the ETag header. +- Asset Definition Extension added to Collections to allow specifying details about Assets that may appear in member Items. +- [Single File Catalog extension](extensions/single-file-stac/README.md) added as a format to have a set of Collections and Items in a single file. +- [Label extension](extensions/label/README.md) added with additional fields for describing labeled data, such as used for training data or from the output of a classification +- Timestamp fields added to `Item`: `created` and `updated` to refer to the datetime the metadata file was created or updated. +- Added Search Metadata API extension which adds fields to a response from a STAC API such as the number of items found and how many were returned. +- ItemCollection class added to spec that is a GeoJSON FeatureCollection of Items, such as what would be returned from a search. Located in item directory. +- `in` operator added to the query extension (to check if value is in a list of values) +- New bands added to the [common band names](extensions/eo/README.md#common-band-names) for the EO extension: yellow, rededge, and 2 narrow NIR bands +- [Scientific extension](extensions/scientific/README.md) can be used in Collections. + +### Fixed +- Updated language, fixed typos and examples. +- Renamed `pc:schema` to `pc:schemas` in the Point Cloud extension. + +### Changes since 0.8.0rc1 +- [Label extension](extensions/label/README.md): + - moved label:classes to be a list of Class Objects from a single Class Object in spec markdown and json schema (matching previous example JSON). + - moved label:overview to be a list of Overview Objects from a single Overview Object in spec markdown and json schema (matching previous example JSON). + - Renamed fields to use plural forms (`label:property` -> `label:properties`, `label:task` -> `label:tasks`, `label:method` -> `label:methods` and `label:overview` -> `label:overviews`) + +## [v0.7.0] - 2019-05-06 + +### Fixed +- Updated language / fixed typos +- Moved static vs dynamic discussion text to catalog best practices document +- Moved hosting of interactive api docs from swaggerhub to [stacspec.org](http://stacspec.org) +- JSON Schemas are now all following the latest JSON Schema version, draft 07. + +### Changed +- No longer require an absolute self link for Items, Collections and Catalogs. +- Reorganized api-spec, added extensions folder to hold API extensions +- Change the fields parameter in the API to allow filtering on any property. +- Refinements to SAR extension, changed several fields from a single array-based field (`sar:absolute_orbit`, `sar:resolution`, `sar:pixel_spacing`, `sar:looks`) to multiple fields with exactly one value. +- Commons extension ability to 'merge' properties is now in the core specification + +### Added +- Catalog best practices document, including recommendations for catalog layouts, html, and self-contained catalogs. +- `page` parameter for STAC API +- Optional `collection` property field in Items (previously part of the Commons extension) +- It is now required to link to `/stac/search/` from `/stac/` +- Added new fields to SAR extension: `sar:incidence_angle`, `sar:relative_orbit`, `sar:observation_direction` +- Added new filter parameters `ids` and `collections` to `/stac/search/` + +### Removed +- Removed the field `sar:off_nadir` from the SAR extension +- JavaScript-based validation + +## [v0.6.2] - 2019-03-01 + +### Fixed +- Fixed several examples and typos, improved descriptions +- Strictly checking the STAC version numbers in the JSON schemas +- Added missing required fields in Item JSON schema +- Changed `id` to `$id` in JSON schemas (draft-06 compatibility) + +### Changed +- Extensions require examples and a JSON schema to get to the maturity level 'Pilot' +- Updated ISERV implementation + +### Added +- Checksum extension +- Data Cube extension +- Point Cloud extension +- SAR extension + +## [v0.6.1] - 2019-01-25 + +### Fixed +- Added `null` as potential data type to `eo:epsg` in the EO extension. +- Fixed several examples and typos. +- Updated JSON Schema versions for uniformity +- Added OpenEO GEE implementation +- Clarified 'intersects' behavior for STAC API + +## [v0.6.0] - 2018-11-06 + +### Fixed +- Reorganized and cleaned up repository. +- Fixed examples throughout. + +### Added +- **Changelog**: This changelog added. +- **Collections added**: Collections are a type of Catalog with additional fields, such as provider and license. Items must belong to a single Collection. +- **Extension maturity**: Protocol for providing maturity classification for extensions based on stability and implementations. +- **Commons extension**: The previous 'Collections' extension is now the 'Commons' extension and allows an Item to inherit properties from its Collection. +- **Datetime-range extension**: Extension for providing start and end datetimes. +- **Scientific extension**: Extension for providings links to scientific publications relating to the data. +- **rel types**: A list of supported `rel` types are provided for use when specifying links, `derived_from` and `license` types added. +- **eo:constellation**: A new field in the EO specification to specify a grouping of platforms. +- **stac_version**: The `stac_version` field is required on all Catalogs (and Collections). +- **JSON schemas**: Added JSON schemas where they were missing. +- **Single Item extension**: Extension to supply License and Providers for single Items when no collection is used. +- **UML Diagram**: See STAC-060-uml.pdf. +- **Development Process**: See process.md for information on the STAC development process. + +### Changed +- **API**: Main catalog endpoint at `/stac`, search endpoint now at `/stac/search`. +- **eo:bands**: The `eo:bands` field is now an array rather than a dictionary, and has been moved inside of `properties` in a STAC Item. +- **Catalog fields**: Catalogs have a smaller number of basic fields: `id`, `stac_version`, `title` (optional), `description`, and `links`. The new Collections type contains additional fields. +- **links**: The links fields are now an array rather than a dictionary. +- **properties**: Fields with the data type array or objects are allowed inside the `properties` in a STAC Item. +- **description**: Description fields now allow formatting with CommonMark. +- **assets**: Fields changed names: `name` to `title` and `mime_type` to `type`. + +### Removed: +* **provider**: Provider field in Items got removed. Use Collections or the Single Item extension instead. +* **license**: License field in Items got removed. Use Collections or the Single Item extension instead. + +## [v0.5.2] - 2018-07-12 + +Minor bug fixes on 0.5.1 for the schema files. Thanks @francbartoli + +## [v0.5.1] - 2018-07-06 + +Minor bug fixes from 0.5.1 release + +* [Update openapi / swagger specs for new 'links'](https://github.com/radiantearth/stac-spec/commit/480d4fb02b4a7e880c7ca01320fe2773260ba595) +* [minor fixes on collection extension](https://github.com/radiantearth/stac-spec/pull/124) - thanks @m-mohr +* [minor cbers example updates](https://github.com/radiantearth/stac-spec/pull/123) - thanks @fredliporace + +## [v0.5.0] - 2018-07-01 + +The 0.5.0 release of the STAC spec is an iteration forward on the spec, with a number of core improvements. Highlights include: + +* **Links is now a dictionary** - This is the most core change done. It aligns the structure with the 'asset' change in 0.5.0, making it easier for clients to look up the link that they want more easily. The schema is updated to this (and actually checks assets better now, thanks @mojodna ) + +* **Transactions Extension** - There is now a transaction extension for the STAC API, thanks to @hgs-msmith and @hgs-trutherford + +* **Collections iterations** @matthewhanson has evolved the collections extension, adding in some namespace type hints on it, and explaining it more clearly. + +* **eo:crs to eo:epsg** In the EO profile @matthewhanson brought in a change to use EPSG code, instead of full Well Known Text, to make it easy to reference. + +Full list of issues and pull requests at + +## [v0.4.1] - 2018-04-24 + +A few minor improvements on the release. ([issues](https://github.com/radiantearth/stac-spec/issues?utf8=%E2%9C%93&q=milestone%3A0.4.1+)) + +* @hgs-msmith got a swagger version of the spec, and made some minor improvements to the openapi version #103 and #102 +* @francbartoli and @m-mohr pointed out some inconsistencies with landsat, so got the openapi updated #106 +* @m-mohr pointed out some issues with landsat example, so updated those #105 +* @hgs-trutherford pointed out that the planet example was a bit confusing, so updated it to the EO profile. + +## [v0.4.0] - 2018-04-06 + +The 0.4.0 is the first 'official' release of the SpatioTemporal Asset Catalog (STAC) specification! + +It is the result of the [ft. collins sprint](https://github.com/radiantearth/community-sprints/tree/master/03072018-ft-collins-co), the second in person meeting of the STAC community. But it also includes +a number of improvements from remote contributors. + +Highlights include: + +* Updates to the core **`Item` JSON specification**, including simplifying to a single datetime, moving thumbnails from 'links' to 'assets', making assets a dictionary for easier lookup and requiring `self` links to be absolute links. + +* Alignment of **STAC API** with the new [WFS3](https://github.com/opengeospatial/WFS_FES/) specification + +* Cleanup of the **static catalog** specification for greater clarity around the catalog + +* A first cut of an **Earth Observation Profile**, as well as a new collections extension to support it. + +* Numerous small improvements and bug fixes. + +See the [milestone 0.4.0 in the issue tracker](https://github.com/radiantearth/stac-spec/milestone/3) for the complete lists of improvements. + +Thanks @hgs-msmith, @matthewhanson, @hgs-trutherford, @rouault, @joshfix, @alkamin, @hemphillda, @jeffnaus and @fredliporace for contributing to the spec directly, and to [everyone](https://github.com/opengeospatial/wfs3hackathon/blob/master/notes/introductions.md#participants) who participated in the [Ft Collins sprint](https://github.com/radiantearth/community-sprints/tree/master/03072018-ft-collins-co) and brought great ideas. + + +[Unreleased]: +[v1.0.0-rc.2]: +[v1.0.0-rc.1]: +[v1.0.0-beta.2]: +[v1.0.0-beta.1]: +[v0.9.0]: +[v0.8.1]: +[v0.8.0]: +[v0.7.0]: +[v0.6.2]: +[v0.6.1]: +[v0.6.0]: +[v0.5.2]: +[v0.5.1]: +[v0.5.0]: +[v0.4.1]: +[v0.4.0]: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..b3776240 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [stac-spec-admins@googlegroups.com](mailto:stac-spec-admins@googlegroups.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at + +[homepage]: + +For answers to common questions about this code of conduct, see + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..6fd9042d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,81 @@ +## Contributing + +Pull Requests are the primary method of contributing to the spec itself, and everyone is welcome to submit +changes. Suggestions for changes to the core will be taken with higher priority if a clear implementation +of STAC has been built that can highlight the problem. If the changes can be done as an [extension](extensions/) +instead of modifying the core files then that route is recommended first, and once there is uptake for the +extension it will be considered for core. + +We consider everyone using the specification to catalog their data to be a 'contributor', as STAC is +really about the end result of more interoperable data, not just creating a spec for the sake of it. +So if you want to help then the best thing you can do is make new catalogs or build software that uses +the spec. And please do give us feedback. The best place to do so is on our +[gitter channel](https://gitter.im/SpatioTemporal-Asset-Catalog/Lobby). If you are interested in helping +but aren't sure where to, then see the [stac-ecosystem](https://github.com/stac-utils/stac-ecosystem) repo +for ideas on projects to advance STAC. The next phase of STAC's evolution will be mostly focused on +this broader ecosystem, while keeping the core spec as stable as we can. + +### Submitting Pull Requests + +Any proposed changes to the specification should be done as pull requests. Please make these +requests against the [dev](https://github.com/radiantearth/stac-spec/tree/dev) branch (this will +require you to switch from the default of 'master', which we keep so it displays first). + +Creating a Pull Request will show our PR template, which includes checkbox reminders for a number +of things. + +* Adding an entry the [CHANGELOG](CHANGELOG.md). If the change is more editorial and minor then this +is not required, but any change to the actual specification should definitely have one. +* Base the PR against dev, as mentioned above - even if the branch was made off of dev this reminds +you to change the base in GitHub's PR creation page. +* Make a ticket in the STAC API repo if anything here affects there. +* Highlight if the PR makes breaking changes to the specification (in beta there can still be +select breaking changes, but after 1.0 this will change) + +All pull requests should submit clean markdown, which is checked by the continuous integration +system. Please use `npm run check` locally, as described in the [next section](#check-files), +to ensure that the checks on the pull request succeed. If it does not then you can look at the +mistakes online, which are the same as running `npm run check` locally would surface. + +All pull requests that modify or create JSON schema files or examples should use [JSON formatter](https://jsonformatter.org/) to keep files consistent across the repo. + +All pull requests additionally require a review of two STAC core team members. Releases are cut +from dev to master (and require 3 approvals), see the [process](process.md) document for more details. + +### Check files + +The same check-markdown and check-examples programs that runs as a check on PR's is part of the repo and can be run locally. +To install you'll need npm, which is a standard part of any [node.js installation](https://nodejs.org/en/download/). Alternatively, you can also use [yarn](https://yarnpkg.com/) instead of npm. In this case replace all occurrences of `npm` with `yarn` below. + +First you'll need to install everything with npm once. Just navigate to the root of the stac-spec repo and on +your command line run: + +```bash +npm install +``` + +Then to do the check for markdown and examples you run: + +```bash +npm run check +``` + +This will spit out the same texts that you see online, and you can then go and fix your markdown or examples. + +To just check the markdown run: + +```bash +npm run check-markdown +``` + +To just check the examples run: + +```bash +npm run check-examples +``` + +To automatically format / pretty-print the examples run: + +```bash +npm run format-examples +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 00000000..cbe1c3e3 --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +stac-logo + +[![CircleCI](https://circleci.com/gh/radiantearth/stac-spec.svg?style=svg)](https://circleci.com/gh/radiantearth/stac-spec) + +## About + +The SpatioTemporal Asset Catalog (STAC) family of specifications aim to +standardize the way geospatial asset metadata is structured and queried. +A "spatiotemporal asset" is any file that represents information about +the Earth at a certain place and time. The original focus was on scenes +of satellite imagery, but the specifications now cover a broad variety of uses, +including sources such as aircraft and drone and data such as hyperspectral optical, +synthetic aperture radar (SAR), video, point clouds, lidar, digital elevation +models (DEM), vector, machine learning labels, and composites like NDVI and +mosaics. STAC is intentionally designed with a minimal core and flexible +extension mechanism to support a broad set of use cases. + +This is advantageous to providers of geospatial data, as they can simply use a +well-designed, standard format and API without needing to design their own proprietary one. +This is advantageous to consumers of geospatial data, as they can use existing libraries +and tools to access metadata, instead of needing to write new code to interact +with each data provider's proprietary formats and APIs. + +The STAC specifications define related JSON object types connected by link +relations to support a [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS)-style traversable +interface and a [RESTful](https://en.wikipedia.org/wiki/Representational_state_transfer) API +providing additional browse and search interfaces. +Typically, several STAC specifications are composed together to create an implementation. +The **Item**, **Catalog**, and **Collection** specifications define a minimal core +of the most frequently used JSON object types. Because of the hierarchical structure +between these objects, a STAC catalog can be implemented in a completely 'static' +manner as a group of hyperlinked Catalog, Collection, and Item URLs, enabling data +publishers to expose their data as a browsable set of files. If more complex query +abilities are desired, such as spatial or temporal predicates, the +**STAC API** [specification](https://github.com/radiantearth/stac-api-spec/) can be +implemented as a web service interface to query over a group of STAC objects, usually +held in a database. + +To the greatest extent possible, STAC uses and extends existing specifications. +The most important object in STAC is an **Item**, which is simply a [GeoJSON](http://geojson.org) **Feature** +with a well-defined set of additional attributes ("foreign members"). The **STAC API** +extends the **[OGC API - Features - Part 1: Core](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html)** +with additional web service endpoints and object attributes. + +## Stability Note + +This specification has matured over the past several years, and is used in +[numerous production deployments](https://stacindex.org/catalogs). +With the 1.0.0 release, implementors should expect that most definitions will remain +stable. Our goal +is to maintain backwards-compatiblity within the core for a long time. +The STAC specification follows [Semantic Versioning](https://semver.org/), so once +1.0.0 is reached, any breaking change will require the spec to go to 2.0.0. + +## Current version and branches + +The [master branch](https://github.com/radiantearth/stac-spec/tree/master) is the 'stable' +version of the spec. It is currently version **1.0.0** of the specification. The +[dev](https://github.com/radiantearth/stac-spec/tree/dev) branch is where active development takes place, +and may have inconsistent examples. Whenever dev stabilizes, a release is cut and we +merge `dev` in to `master`. So `master` should be stable at any given time. +More information on how the STAC development process works can be found in +[process.md](process.md). + +## Communication + +Our [gitter channel](https://gitter.im/SpatioTemporal-Asset-Catalog/Lobby) is +the best place to ask questions or provide feedback. The majority of communication about the evolution of +the specification takes place in the [issue tracker](https://github.com/radiantearth/stac-spec/issues) and in +[pull requests](https://github.com/radiantearth/stac-spec/pulls). + +## In this Repository + +This repository contains the core object type specifications, [examples](examples/), +validation schemas, and documentation about the context and plans for the evolution of the +specification. Each folder contains a README explaining the layout of the folder, +the main specification document, examples, and validating schemas. + +Additionally, the [STAC API specification](https://github.com/radiantearth/stac-api-spec/) +provides API endpoints, based on the [OGC API - Features](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html) standard, +that enable clients to search for Item objects that match their filtering criteria. + +The **Item**, **Catalog**, **Collection**, and **STAC API** specifications are intended to be +used together, but are designed so each piece is small, self-contained, and reusable in other contexts. + +* **[Overview](overview.md)** describes the three core object type specifications and how they relate to one another. +* **[Item Specification](item-spec/)** defines a STAC **Item**, which is a [GeoJSON](http://geojson.org) **Feature** +with additional fields ("foreign members") for attributes like time and links to related entities and assets +(including thumbnails). This is the core entity that describes the data to be discovered. +* **[Catalog Specification](catalog-spec/)** specifies a structure to link various STAC Items together to be crawled or browsed. It is a +simple, flexible JSON file of links to Items, Catalogs or Collections that can be used in a variety of ways. +* **[Collection Specification](collection-spec/)** provides additional information about a spatio-temporal collection of data. +In the context of STAC it is most likely a related group of STAC Items that is made available by a data provider. +It includes things like the spatial and temporal extent of the data, the license, keywords, etc. +It enables discovery at a higher level than individual Item objects, providing a simple way to describe sets of data. +* **[Examples](examples/):** The *[examples/](examples/)* folder contains examples for all three specifications, linked together to form two +complete examples. Each spec and extension links in to highlight particular files that demonstrate key concepts. +* **[Extensions](extensions/README.md)** describe how STAC can use extensions that extend the functionality of the core spec or +add fields for specific domains. Extensions can be published anywhere, although the preferred location for public extensions is in the [GitHub `stac-extensions` organization](https://github.com/stac-extensions). +* **Additional documents:** The supporting documents include a complementary [best practices](best-practices.md) +document, and information on contributing (links in the next section). We also maintain a [changelog](CHANGELOG.md) of +what was modified in each version. + +## Contributing + +Anyone building software that catalogs imagery or other geospatial assets is welcome to collaborate. +Beforehand, please review our [guidelines for contributions](CONTRIBUTING.md) and [code of conduct](CODE_OF_CONDUCT.md). +You may also be interested in our overall [process](process.md), and the [principles](principles.md) that guide our +collaboration diff --git a/STAC-UML.drawio b/STAC-UML.drawio new file mode 100644 index 00000000..fca34d35 --- /dev/null +++ b/STAC-UML.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/STAC-UML.pdf b/STAC-UML.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c3e02556007c08643fd135354dab0dc088fd2f07 GIT binary patch literal 46890 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 state-level) and +then year, month, day. Or do the opposite - date and then location. Making a huge unordered list is technically allowed, +but not helpful for discovery of data. Thus it is generally considered a best practice to make use of sub-catalogs to +keep the size of each sub-catalog under a megabyte. If your sub-catalog lists tens of thousands of child items then you +should consider an additional way to break it up. + +We encourage people to explore new structures of linking data, but the following list is what a number of implementors +ended up doing. Following these recommendations makes for more legible catalogs, and many tools operate more efficiently +if you follow these recommendations. + +1. Root documents (Catalogs / Collections) should be at the root of a directory tree containing the static catalog. +2. Catalogs should be named `catalog.json` and Collections should be named `collection.json`. +3. Items should be named `.json`. +4. Sub-Catalogs should be stored in subdirectories of their parent (and only 1 subdirectory deeper than a document's parent) (e.g. `.../sample/sub1/catalog.json`). +5. Items should be stored in subdirectories of their parent Catalog. +This means that each Item and its assets are contained in a unique subdirectory. +6. Limit the number of Items in a Catalog or sub-Catalog, grouping / partitioning as relevant to the dataset. +7. Use structural elements (Catalog and Collection) consistently across each 'level' of your hierarchy. For example, if levels 2 and 4 of the hierarchy only contain Collections, +don't add a Catalog at levels 2 and 4. + +#### Dynamic Catalog Layout + +While these recommendations were primarily written for [static catalogs](#static-catalogs), they apply +equally well to [dynamic catalogs](#dynamic-catalogs). Subdirectories of course would just be URL paths +generated dynamically, but the structure would be the same as is recommended. + +One benefit of a dynamic catalog is that it can generate various 'views' of the catalog, exposing the same Items in +different sub-catalog organization structures. For example one catalog could divide sub-catalogs by date and another +by providers, and users could browse down to both. The leaf Items should just be linked to in a single canonical location +(or at least use a rel link that indicates the location of the canonical one). It is recommended that dynamic catalogs +provide multiple 'views' to allow users to navigate in a way that makes sense to them, providing multiple 'sub-catalogs' +from the root Catalog that enable different paths to browse (country/state, date/time, constellation/satellite, etc). But the +canonical 'rel' link should be used to designate the primary location of the Item to search engine crawlers. + +#### Mixing STAC Versions + +Although it is allowed to mix STAC versions, it should be used carefully as clients may not support all versions so that +the catalog could be of limited use to users. A Catalog or Collection linking to differently versioned Sub-Catalogs or Sub-Collections +is a common use case when multiple data source are combined. Client developers should be aware of this use case. Nevertheless, it +is strongly recommended that Catalogs don't contain differently versioned Items so that users/clients can at least use and/or download +consistent (Sub-)Catalogs containing either all or no data. Collections that are referenced from Items should always use the same +STAC version. Otherwise some behaviour of functionality may be unpredictable (e.g. merging common fields into Items or reading summaries). + +### Using Summaries in Collections + +One of the strongest recommendations for STAC is to always provide [summaries](collection-spec/collection-spec.md#summaries) in +your Collections. The core team decided to not require them, in case there are future situations where providing a summary +is too difficult. The idea behind them is not to exhaustively summarize every single field in the Collection, but to provide +a bit of a 'curated' view. + +Some general thinking on what to summarize is as follows: + +* Any field that is a range of data (like numbers or dates) is a great candidate to summarize, to give people a sense what values +the data might be. For example in overhead imagery, a +[`view:off_nadir`](https://github.com/stac-extensions/view/blob/main/README.md#item-properties-and-item-asset-fields) with a range of 0 to 3 would tell people this +imagery is all pretty much straight down, while a value of 15 to 40 would tell them that it's oblique imagery, or 0 to 60 that it's +a Collection with lots of different look angles. + +* Fields that have only one or a handful of values are also great to summarize. Collections with a single satellite may +use a single [`gsd`](item-spec/common-metadata.md#instrument) field in the summary, and it's quite useful for users to know +that all data is going to be the same resolution. Similarly it's useful to know the names of all the +[`platform` values](item-spec/common-metadata.md#instrument) that are used in the Collection. + +* It is less useful to summarize fields that have numerous different discrete values that can't easily be represented +in a range. These will mostly be string values, when there aren't just a handful of options. For example if you had a +'location' field that gave 3 levels of administrative region (like 'San Francisco, California, United States') to help people +understand more intuitively where a shot was taken. If your Collection has millions of Items, or even hundreds, you don't want +to include all the different location string values in a summary. + +* Fields that consist of arrays are more of a judgement call. For example [`instruments`](item-spec/common-metadata.md#instrument) +is straightforward and recommended, as the elements of the array are a discrete set of options. On the other hand +[`proj:transform`](https://github.com/stac-extensions/projection/blob/main/README.md#projtransform) makes no sense to summarize, as the union of all the values +in the array are meaningless, as each Item is describing its transform, so combining them would just be a bunch of random numbers. +So if the values contained in the array are independently meaningful (not interconnected) and there aren't hundreds of potential +values then it is likely a good candidate to summarize. + +We do highly recommend including an [`eo:bands`](https://github.com/stac-extensions/eo/blob/main/README.md#eobands) summary if your Items implement `eo:bands`, +especially if it represents just one satellite or constellation. This should be a union of all the potential bands that you +have in assets. It is ok to only add the summary at the Collection level without putting an explicit `eo:bands` summary at the +`properties` level of an Item, since that is optional. This gives users of the Collection a sense of the sensor capabilities without +having to examine specific Items or aggregate across every Item. + +Note that the ranges of summaries don't have to be exact. If you are publishing a catalog that is constantly updating with +data from a high agility satellite you can put the `view:off_nadir` range to be the expected values, based on the satellite +design, instead of having it only represent the off nadir angles that are Items for assets already captured in the catalog. +We don't want growing catalogs to have to constantly check and recalculate their summaries whenever new data comes in - its +just meant to give users a sense of what types of values they could expect. + +### Use of links + +The STAC specifications allow both relative and absolute links, and says that `self` links are not required, but are +strongly recommended. This is what the spec must say to enable the various use cases, but there is more subtlety for when it +is essential to use different link types. The best practice is to use one of the below catalog types, applying the link +recommendations consistently, instead of just haphazardly applying relative links in some places and absolute ones in other places. + +#### Self-contained Catalogs + +A 'self-contained catalog' is one that is designed for portability. Users may want to download a catalog from online and be +able to use it on their local computer, so all links need to be relative. Or a tool that creates catalogs may need to work +without knowing the final location that it will live at online, so it isn't possible to set absolute 'self' URL's. These use +cases should utilize a catalog that follows the listed principles: + +* **Only relative href's in structural `links`**: The full catalog structure of links down to sub-catalogs and Items, and their +links back to their parents and roots, should be done with relative URL's. The structural rel types include `root`, `parent`, +`child`, `item`, and `collection`. Other links can be absolute, especially if they describe a resource that makes less sense in +the catalog, like [sci:doi](https://github.com/stac-extensions/scientific/blob/main/README.md#item-and-collection-fields), +`derived_from` or even `license` (it can be nice to include the license in the catalog, but some licenses live at a canonical +online location which makes more sense to refer to directly). This enables the full catalog to be downloaded or +copied to another location and to still be valid. This also implies no `self` link, as that link must be absolute. + +* **Use Asset `href` links consistently**: The links to the actual assets are allowed to be either relative or absolute. There +are two types of 'self-contained catalogs'. + +#### Self-contained Metadata Only + +These consist of just the STAC metadata (Collection, Catalog and Item files), and uses absolute href +links to refer to the online locations of the assets. + +#### Self-contained with Assets + +These use relative href links for the assets, and includes them in the folder structure. +This enables offline use of a catalog, by including all the actual data, referenced locally. + +Self-contained catalogs tend to be used more as static catalogs, where they can be easily passed around. But often they will +be generated by a more dynamic STAC service, enabling a subset of a catalog or a portion of a search criteria to be downloaded +and used in other contexts. That catalog could be used offline, or even published in another location. + +Self-contained catalogs are not just for offline use, however - they are designed to be able to be published online and to live +on the cloud in object storage. They just aim to ease the burden of publishing, by not requiring lots of updating of links. +Adding a single `self` link at the root is recommended for online catalogs, turning it into a 'relative published catalog', as detailed below. This anchors it in an online location and enables provenance tracking. + +#### Published Catalogs + +While STAC is useful as a portable format to move between systems, the goal is really to enable search. While any combination +of absolute and relative links is technically allowed by the specification, it is strongly recommended to follow one of the +patterns described below when publishing online. Many clients will not properly handle arbitrary mixes of absolute and relative +href's. + +We refer to a 'published catalog' as one that lives online in a stable location, and uses `self` links to establish its location and +enable easy provenance tracking. There are two types of published catalogs: + +#### Absolute Published Catalog + +This is a catalog that uses absolute links for everything, both in the `links` objects and in the +`asset` hrefs. It includes `self` links for every Item. Generally these are implemented by dynamic catalogs, as it is quite +easy for them to generate the proper links dynamically. But a static catalog that knows its published location could easily +implement it. + +#### Relative Published Catalog + +This is a self-contained catalog as described above, except it includes an absolute `self` link at +the root catalog, to identify its online location. This is designed so that a self-contained catalog (of either type, with its +assets or just metadata) can be 'published' online +by just adding one field (the self link) to its root catalog. All the other links should remain the same. The resulting catalog +is no longer compliant with the self-contained catalog recommendations, but instead transforms into a 'relative published catalog'. +With this, a client may resolve Item and sub-catalog self links by traversing parent and root links, but requires reading +multiple sources to achieve this. + +So if you are writing a STAC client it is recommended to start with just supporting these two types of published catalogs. In +turn, if your data is published online publicly or for use on an intranet then following these recommendations will ensure +that a wider range of clients will work with it. + +### Using Relation Types + +Implementors of STAC are highly recommended to be quite liberal with their `links`, and to use the `rel` field (in conjunction +with the `type` field) to communicate the structure and content of related entities. While each STAC spec describes some of the +'custom' relations STAC has set, the ideal is to reuse official [IANA Link Relation +Types](https://www.iana.org/assignments/link-relations/link-relations.xhtml) as much as possible. The following table describes +a number of the common official relations that are used in production STAC implementations. + +| Type | Description | +| ------------ | ------------------------------------------------------------ | +| alternate | It is recommended that STAC Items are also available as HTML, and should use this rel with `"type" : "text/html"` to tell clients where they can get a version of the Item or Collection to view in a browser. See [STAC on the Web in Best Practices](#stac-on-the-web) for more information. | +| canonical | The URL of the [canonical](https://en.wikipedia.org/wiki/Canonical_link_element) version of the Item or Collection. API responses and copies of catalogs should use this to inform users that they are direct copy of another STAC Item, using the canonical rel to refer back to the primary location. | +| via | The URL of the source metadata that this STAC Item or Collection is created from. Used similarly to canonical, but refers back to a non-STAC record (Landsat MTL, Sentinel tileInfo.json, etc) | +| prev | Indicates that the link's context is a part of a series, and that the previous in the series is the link target. Typically used in STAC by API's, to return smaller groups of Items or Catalogs. | +| next | Indicates that the link's context is a part of a series, and that the next in the series is the link target. Typically used in STAC by API's, to return smaller groups of Items or Catalogs. | + +### Versioning for Catalogs + +In the Item and Collection STAC JSON, versions and deprecation can be indicated with the [Versioning Indicators Extension](https://github.com/stac-extensions/version). + +The [Items and Collections API Version Extension](https://github.com/stac-extensions/version/) provides endpoints and +semantics for keeping and accessing previous versions of Collections and Items. The same semantics can be used in static +catalogs to preserve previous versions of the documents and link them together. + +In order to achieve this, the static catalog must make sure that for every record created, a copy of the record is also +created in a separate location and it is named with the version id adopted by the catalog. See +[here](https://github.com/stac-extensions/version/blob/main/README.md#version-id) for recommendations on versioning schema. + +The main record should also provide a link to the versioned record following the linking patterns described +[here](https://github.com/stac-extensions/version/blob/main/README.md#relation-types). For every update to the record, the same +cycle is repeated: + +1. Add link from the updated record to the previous version +2. Create a copy of the updated record and name it correctly + +#### Example + +When the record `my_item.json` is created, a copy of it is also created. `my_item.json` includes `permalink` to `my_item_01.json`. The version suffix of the file name is taken from the version field of the record when it is available. + +- `root / collections / example_collection / items / my_item / my_item.json` +- `root / collections / example_collection / items / my_item / my_item_01.json` + +When `my_item.json` is updated, the new `my_item.json` includes a link to `my_item_01.json` and is also copied to `my_item_02.json`. This ensures that `my_item_02.json` includes a link to `my_item_01.json` + +- `root / collections / example_collection / items / my_item / my_item.json` +- `root / collections / example_collection / items / my_item / my_item_01.json` +- `root / collections / example_collection / items / my_item / my_item_02.json` + +### Static to Dynamic best practices + +Many implementors are using static catalogs to be the reliable core of their dynamic services, or layering their STAC API +on top of any static catalog that is published. These are some recommendations on how to handle this: + +#### Ingestion and links + +Implementors have found that it's best to 'ingest' a static STAC into an internal datastore (often elasticsearch, but a +traditional database could work fine too) and then generate the full STAC API responses from that internal representation. +There are instances that have the API refer directly to the static STAC Items, but this only works well if the static STAC +catalog is an 'absolute published catalog'. So the recommendation is to always use absolute links - either in the static +published catalog, or to create new absolute links for the STAC search/ endpoint +responses, with the API's location at the base url. The `/` endpoint with the catalog could either link directly +to the static catalog, or can follow the 'dynamic catalog layout' recommendations above with a new set of URL's. + +Ideally each Item would use its `links` to provide a reference back to the static location. The location of the static +Item should be treated as the canonical location, as the generated API is more likely to move or be temporarily down. The +spec provides the `derived_from` rel field, which fits well enough, but `canonical` is likely the more appropriate one +as everything but the links should be the same. + +#### Keep catalogs in sync with cloud notification and queue services + +There is a set of emerging practices to use services like Amazon's Simple Queue Service (SQS) and Simple Notification Service +(SNS) to keep catalogs in sync. There is a great [blog post on the CBERS STAC implementation on AWS](https://aws.amazon.com/blogs/publicsector/keeping-a-spatiotemporal-asset-catalog-stac-up-to-date-with-sns-sqs/). The core +idea is that a static catalog should emit a notification whenever it changes. The recommendation for SNS is to use the STAC +Item JSON as the message body, with some fields such as a scene’s datetime and geographic bounding box that allows +basic geographic filtering from listeners. + +The dynamic STAC API would then listen to the notifications and update its internal datastore whenever new data comes into +the static catalog. Implementors have had success using AWS Lambda to do a full 'serverless' updating of the elasticsearch +database, but it could just as easily be a server-based process. + +## How to Differentiate STAC Files + +Any tool that crawls a STAC implementation or encounters a STAC file in the wild needs a clear way to determine if it is an Item, +Collection, Catalog or [ItemCollection](https://github.com/radiantearth/stac-api-spec/tree/v1.0.0-beta.1/fragments/itemcollection) +(part of the [STAC API spec](https://github.com/radiantearth/stac-api-spec/tree/v1.0.0-beta.1)). As of 1.0.0 this is done primarily +with the `type` field, and secondarily in Items with `stac_version`, or optionally the `rel` of the link to it. + +```shell +if type is 'Collection' + => Collection +else if type is 'Catalog' + => Catalog +else if type is 'Feature' and stac_version is defined + => Item +else if type is 'FeatureCollection' and stac_version is defined + => ItemCollection +else + => Invalid (JSON) +``` + +When crawling a STAC implementation, one can also make use of the [relation type](catalog-spec/catalog-spec.md#relation-types +) (`rel` field) when following a link. If it is an `item` rel type then the file must be a STAC Item. If it is `child`, `parent` or +`root` then it must be a Catalog or a Collection, though the final determination between the two requires looking at the the `type` field +in the Catalog or Collection JSON that is linked to. Note that there is also a `type` field in STAC Link and Asset objects, but that +is for the Media Type, but there are not specific media types for Catalog and Collection. See the sections on [STAC media +types](catalog-spec/catalog-spec.md#media-types), and [Asset media types](item-spec/item-spec.md#asset-media-type) for more information. + +In versions of STAC prior to 1.0 the process was a bit more complicated, as there was no `type` field for catalogs and collections. +See [this issue comment](https://github.com/radiantearth/stac-spec/issues/889#issuecomment-684529444) for a heuristic that works +for older STAC versions. diff --git a/catalog-spec/README.md b/catalog-spec/README.md new file mode 100644 index 00000000..a2626d22 --- /dev/null +++ b/catalog-spec/README.md @@ -0,0 +1,34 @@ +# STAC Catalog Specification + +A STAC [Catalog](catalog-spec.md) is a top-level object that logically groups other Catalog, Collection, +and [Item](../item-spec/item-spec.md) objects. A Catalog contains an array of Link objects to these other +objects and can include additional metadata to describe the objects contained therein. It is defined in full +in the [STAC Catalog Specification](catalog-spec.md). + +For more information on how the parts of STAC fit together see the [overview](../overview.md) document. + +A Catalog is typically the "entry point" into a STAC object hierarchy. For example, the root endpoint ("landing page") of a STAC API implementation is a Catalog. For many static STAC catalogs (e.g., those defined only by a set of files on disk or in a cloud object store), the root URL points to a Catalog that acts as the starting point to traverse the entire catalog of Catalog, Collection, and Item objects. + +While STAC Catalogs mostly describe a structure of links and Items, a key related specification is the [STAC Collection Specification](../collection-spec/collection-spec.md), +which contains fields that further describe the group of Items in a Catalog. + +A STAC Catalog requires a subset of the fields required by a Collection. These are distinguished from one another by the `type` field, which will have the value `Catalog` or `Collection`. This means that a Collection can be changed to a Catalog simply by changing this `type` field. The parent-child relationships among Catalogs and Collections are for objects of these types, as there is no subtyping relationship between the Collection and Catalog types, even through they share field names. + +Catalogs are designed so that a simple file server on the web or object store like Amazon S3 can store JSON that defines a +full Catalog. More dynamic services can also return a Catalog structure, and the [STAC API](https://github.com/radiantearth/stac-api-spec) +specification contains an OpenAPI definition of the standard way to do this, at the `/` endpoint. + +## In this directory + +**Specification:** The main Catalog specification is in *[catalog-spec.md](catalog-spec.md)*. +It includes in depth explanation of the structures and fields. + +**Schemas:** The schemas to validate the core Catalog definition are found in the *[json-schema/](json-schema/)* folder. +The primary one is *[catalog.json](json-schema/catalog.json)*. + +## Catalog Evolution + +The Catalog specification is maturing, but it is still relatively early days. The core of Catalog has been defined very +narrowly, to just describe a structure that can be followed by people or machines, so most additional functionality will +be defined in additional specifications and extensions. The only anticipated changes to the core of Catalog are to add in +additional extension mechanisms for others to use. diff --git a/catalog-spec/catalog-spec.md b/catalog-spec/catalog-spec.md new file mode 100644 index 00000000..032d85a3 --- /dev/null +++ b/catalog-spec/catalog-spec.md @@ -0,0 +1,127 @@ +# STAC Catalog Specification + +- [Catalog fields](#catalog-fields) + - [Additional Field Information](#additional-field-information) + - [stac_version](#stac_version) + - [stac_extensions](#stac_extensions) + - [Link Object](#link-object) + - [Relation types](#relation-types) +- [Media Types](#media-types) + - [Media Type for STAC Catalogs](#media-type-for-stac-catalogs) + - [STAC Media Types](#stac-media-types) +- [Extensions](#extensions) + +This document explains the structure and content of a STAC **Catalog** object. A STAC Catalog object +represents a logical group of other Catalog, +[Collection](../collection-spec/collection-spec.md), and [Item](../item-spec/item-spec.md) objects. +These Items can be linked to directly from a Catalog, or the Catalog can link to other Catalogs (often called +sub-catalogs) that contain links to Collections and Items. The division of sub-catalogs is up to the implementor, +but is generally done to aid the ease of online browsing by people. + +A Catalog object will typically be the entry point into a STAC catalog. Their +purpose is discovery: to be browsed by people or be crawled +by clients to build a searchable index. + +Any JSON object that contains all the required fields is a valid STAC Catalog object. + +- [Examples](../examples/) + - See an example [catalog.json](../examples/catalog.json). The [collection.json](../examples/collection.json) is also a valid + Catalog file, demonstrating linking to items (it is also a Collection, so has additional fields) +- [JSON Schema](json-schema/catalog.json) + +The [Catalog section of the Overview](../overview.md#catalog-overview) document provides background information on +the structure of Catalogs as well as links to best practices. This specification lays out the requirements +and fields to be compliant. + +This Catalog specification primarily defines a structure for information to be discoverable. Any use +that is publishing a set of related spatiotemporal assets is strongly recommended to also use the +STAC Collection specification to provide additional information about the set of Items +contained in a Catalog, in order to give contextual information to aid in discovery. Every STAC Collection is +also a valid STAC Catalog. + +## Catalog fields + +| Element | Type | Description | +| --------------- | ------------- | ------------------------------------------------------------ | +| type | string | **REQUIRED.** Set to `Catalog` if this Catalog only implements the Catalog spec. | +| stac_version | string | **REQUIRED.** The STAC version the Catalog implements. | +| stac_extensions | \[string] | A list of extension identifiers the Catalog implements. | +| id | string | **REQUIRED.** Identifier for the Catalog. | +| title | string | A short descriptive one-line title for the Catalog. | +| description | string | **REQUIRED.** Detailed multi-line description to fully explain the Catalog. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | +| summaries | Map | A map of property summaries, either a set of values or statistics such as a range. More info in the [Collection spec](../collection-spec/collection-spec.md#summaries). | +| links | [[Link Object](#link-object)] | **REQUIRED.** A list of references to other documents. | + +### Additional Field Information + +#### stac_version + +In general, STAC versions can be mixed, but please keep the [recommended best practices](../best-practices.md#mixing-stac-versions) in mind. + +#### stac_extensions + +A list of extensions the Catalog implements. +This list must only contain extensions that extend the Catalog itself, see the the 'Scope' column in the list of +extensions. This does NOT declare the extensions of child Catalog, Collection, or Item +objects. The list contains URLs to the JSON Schema files it can be validated against. + +### Link Object + +This object describes a relationship with another entity. Data providers are advised to be liberal +with links. + +| Field Name | Type | Description | +| ---------- | ------ | ----------- | +| href | string | **REQUIRED.** The actual link in the format of an URL. Relative and absolute links are both allowed. | +| rel | string | **REQUIRED.** Relationship between the current document and the linked document. See chapter ["Relation types"](#relation-types) for more information. | +| type | string | [Media type](#media-types) of the referenced entity. | +| title | string | A human readable title to be used in rendered displays of the link. | + +For a full discussion of the situations where relative and absolute links are recommended see the +['Use of links'](../best-practices.md#use-of-links) section of the STAC best practices. + +#### Relation types + +The following types are commonly used as `rel` types in the Link Object of a STAC Catalog: + +| Type | Description | +| ------- | ----------- | +| self | STRONGLY RECOMMENDED. *Absolute* URL to the location that the Catalog file can be found online, if available. This is particularly useful when in a download package that includes metadata, so that the downstream user can know where the data has come from. | +| root | STRONGLY RECOMMENDED. URL to the root STAC Catalog or [Collection](../collection-spec/README.md). Catalogs should include a link to their root, even if it's the root and points to itself. | +| parent | URL to the parent STAC Catalog or Collection. Non-root Catalogs should include a link to their parent. | +| child | URL to a child STAC Catalog or Collection. | +| item | URL to a STAC Item. | + +**Note:** A link to at least one `item` or `child` Catalog is **REQUIRED**. + +There are additional `rel` types in the [Using Relation Types](../best-practices.md#using-relation-types) best practice, but as +they are more typically used in Collections, as Catalogs tend to just be used to structure STAC organization, so tend to just use +the ones above. + +## Media Types + +One of the best ways to help inform web clients about the content in a link is to use a common [Media +Type](https://en.wikipedia.org/wiki/Media_type) in the `type` field. In STAC the `type` field is used in both the +'[Link](#link-object)'' and '[Asset](../item-spec/item-spec.md#asset-object)' Objects. It is quite useful for STAC browsers to better determine +what to render and display to users searching and browsing the Catalog. Media types are often referred to by the +now deprecated term "MIME types". + +### Media Type for STAC Catalogs + +A STAC Catalog is a JSON file ([RFC 8259](https://tools.ietf.org/html/rfc8259)), and thus should use the +[`application/json`](https://tools.ietf.org/html/rfc8259#section-11) as the [Media Type](https://en.wikipedia.org/wiki/Media_type) +(previously known as the MIME Type). + +### STAC Media Types + +The following table lists the Media Types to use for STAC structures. + +| Media Type | Description | +| ---------------------- | ---------------------------------------------------------- | +| `application/geo+json` | A STAC [Item](../item-spec/item-spec.md) | +| `application/json` | A STAC Catalog | +| `application/json` | A STAC [Collection](../collection-spec/collection-spec.md) | + +## Extensions + +The [extensions page](../extensions/) gives an overview about relevant extensions for STAC Catalogs. diff --git a/catalog-spec/json-schema/catalog-core.json b/catalog-spec/json-schema/catalog-core.json new file mode 100644 index 00000000..503d7a66 --- /dev/null +++ b/catalog-spec/json-schema/catalog-core.json @@ -0,0 +1,139 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/catalog-spec/json-schema/catalog-core.json#", + "title": "Common STAC Catalog + Collection Fields", + "description": "This object represents the common fields shared by Catalogs and Collections", + "allOf": [ + { + "$ref": "#/definitions/catalogCore" + } + ], + "definitions": { + "catalogCore": { + "title": "Catalog Core Fields", + "type": "object", + "required": [ + "stac_version", + "id", + "description", + "links" + ], + "properties": { + "stac_version": { + "title": "STAC version", + "type": "string", + "const": "1.0.0-rc.2" + }, + "stac_extensions": { + "title": "STAC extensions", + "type": "array", + "uniqueItems": true, + "items": { + "anyOf": [ + { + "title": "Reference to a JSON Schema", + "type": "string", + "format": "iri" + }, + { + "title": "Reference to a core extension", + "type": "string" + } + ] + } + }, + "id": { + "title": "Identifier", + "type": "string", + "minLength": 1 + }, + "title": { + "title": "Title", + "type": "string" + }, + "description": { + "title": "Description", + "type": "string", + "minLength": 1 + }, + "links": { + "title": "Links", + "type": "array", + "items": { + "$ref": "#/definitions/link" + } + }, + "summaries": { + "$ref": "#/definitions/summaries" + } + } + }, + "link": { + "type": "object", + "required": [ + "rel", + "href" + ], + "properties": { + "href": { + "title": "Link reference", + "type": "string", + "format": "iri-reference", + "minLength": 1 + }, + "rel": { + "title": "Link relation type", + "type": "string", + "minLength": 1 + }, + "type": { + "title": "Link type", + "type": "string" + }, + "title": { + "title": "Link title", + "type": "string" + } + } + }, + "summaries": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "title": "Stats", + "type": "object", + "required": [ + "minimum", + "maximum" + ], + "properties": { + "minimum": { + "title": "Minimum value", + "type": [ + "number", + "string" + ] + }, + "maximum": { + "title": "Maximum value", + "type": [ + "number", + "string" + ] + } + } + }, + { + "title": "Set of values", + "type": "array", + "minItems": 1, + "items": { + "description": "Any data type could occur." + } + } + ] + } + } + } +} \ No newline at end of file diff --git a/catalog-spec/json-schema/catalog.json b/catalog-spec/json-schema/catalog.json new file mode 100644 index 00000000..0f2c110f --- /dev/null +++ b/catalog-spec/json-schema/catalog.json @@ -0,0 +1,29 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/catalog-spec/json-schema/catalog.json#", + "title": "STAC Catalog Specification", + "description": "This object represents Catalogs in a SpatioTemporal Asset Catalog.", + "allOf": [ + { + "$ref": "catalog-core.json" + }, + { + "$ref": "#/definitions/catalog" + } + ], + "definitions": { + "catalog": { + "title": "Catalog", + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "title": "Type of STAC entity", + "const": "Catalog" + } + } + } + } +} diff --git a/collection-spec/README.md b/collection-spec/README.md new file mode 100644 index 00000000..6b5a0233 --- /dev/null +++ b/collection-spec/README.md @@ -0,0 +1,43 @@ +# STAC Collection Specification + +A STAC [Collection](collection-spec.md) object is used to describe a group of related +Items. It builds on fields defined for a [Catalog](../catalog-spec/catalog-spec.md) object +by further defining and explaining logical groups of [Items](../item-spec/item-spec.md). A +Collection can have parent Catalog and Collection objects, as well as child Item, Catalog, +and Collection objects. These parent-child relationships among objects of these types, as there is no +subtyping relationship between the Collection and Catalog types, even through they share field names. + +A Collection provides a flexible mechanism to provide additional metadata about a set of Items. +Generally, is used to describe a set of assets that +are defined with the same properties and share higher-level metadata. There is no +standardized name for this sort of logical grouping, but other places it is called a " +dataset series" (ESA, ISO 19115), "collection" (CNES, NASA), "dataset" (JAXA), or "product" +(JAXA). In GIS terms, the Items are +'[features](https://en.wikipedia.org/wiki/Simple_Features)' (that link to assets) and +a Collection is the 'layer'. STAC uses the same terms as the +[OGC Features API](https://ogcapi.ogc.org/features/). A STAC Collection is a valid +[Feature API Collection](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html#example_4), +extending it with additional fields. + +Thus, the additional fields in a Collection detail the type of information a user would want to +know about the group of Items it contains. Items are required to provide a link back to their +collection definition. But the Collection is independent of STAC Items and STAC Catalogs, and thus +other parties can also use this specification standalone, as a way to describe collections in a +lightweight way. For more details on how the STAC specs fit together see the [overview](../overview.md) +document. + +## In this directory + +**Specification:** The main STAC Collection specification is in *[collection-spec.md](collection-spec.md)*. It includes an overview and in depth explanation of the +structures and fields. + +**Schemas:** The schemas to validate the STAC Collection definition are found in the +*[json-schema/](json-schema/)* folder. The primary one is *[collection.json](json-schema/collection.json)*. + +## Collection Flexibility + +STAC Collections are defined for flexibility. They only require a handful of fields, and +implementors are free to add most any JSON field or object that they want via extensions. This flexibility and extensibility is a design goal, so that it is quite easy to implement a collection and be able to adapt it to most any data model. + +Implementors are encouraged to do what makes sense for them, and to check out the [examples](../examples/) and +[other implementations](https://stacindex.org/catalogs) for current best practices. diff --git a/collection-spec/collection-spec.md b/collection-spec/collection-spec.md new file mode 100644 index 00000000..f781bb91 --- /dev/null +++ b/collection-spec/collection-spec.md @@ -0,0 +1,260 @@ +# STAC Collection Specification + +- [Overview](#overview) +- [Collection fields](#collection-fields) + - [Additional Field Information](#additional-field-information) + - [stac_version](#stac_version) + - [stac_extensions](#stac_extensions) + - [id](#id) + - [license](#license) + - [summaries](#summaries) + - [assets](#assets) + - [Extent Object](#extent-object) + - [Spatial Extent Object](#spatial-extent-object) + - [Temporal Extent Object](#temporal-extent-object) + - [Provider Object](#provider-object) + - [Link Object](#link-object) + - [Relation types](#relation-types) + - [Asset Object](#asset-object) + - [Stats Object](#stats-object) +- [Media Type for STAC Collections](#media-type-for-stac-collections) +- [Standalone Collections](#standalone-collections) + +## Overview + +The STAC Collection Specification defines a set of common fields to describe a group of Items that share properties and metadata. The +Collection Specification shares all fields with the STAC [Catalog Specification](../catalog-spec/catalog-spec.md) (with different allowed +values for `type` and `stac_extensions`) and adds fields to describe the whole dataset and the included set of Items. Collections +can have both parent Catalogs and Collections and child Items, Catalogs and Collections. + +A STAC Collection is represented in JSON format. Any JSON object that contains all the required fields is a valid STAC Collection and also a valid STAC Catalog. + +STAC Collections are compatible with the [Collection](http://docs.opengeospatial.org/is/17-069r3/17-069r3.html#example_4) JSON +specified in [*OGC API - Features*](https://ogcapi.ogc.org/features/), but they are extended with additional fields. + +* [Examples](../examples/): + * Sentinel 2: A basic standalone example of a [Collection](../examples/collection-only/collection.json) without Items. + * Simple Example: A [Collection](../examples/collection.json) that links to 3 example Items. + * Extension Collection: An additional [Collection](../examples/extensions-collection/collection.json), which is used to highlight + various [extension](../extensions) functionality, but serves as another example. +* [JSON Schema](json-schema/collection.json) + +## Collection fields + +| Element | Type | Description | +| --------------- | ------------------------------------------------ | ------------------------------------------------------------ | +| type | string | **REQUIRED.** Must be set to `Collection` to be a valid Collection. | +| stac_version | string | **REQUIRED.** The STAC version the Collection implements. | +| stac_extensions | \[string] | A list of extension identifiers the Collection implements. | +| id | string | **REQUIRED.** Identifier for the Collection that is unique across the provider. | +| title | string | A short descriptive one-line title for the Collection. | +| description | string | **REQUIRED.** Detailed multi-line description to fully explain the Collection. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | +| keywords | \[string] | List of keywords describing the Collection. | +| license | string | **REQUIRED.** Collection's license(s), either a SPDX [License identifier](https://spdx.org/licenses/), `various` if multiple licenses apply or `proprietary` for all other cases. | +| providers | \[[Provider Object](#provider-object)] | A list of providers, which may include all organizations capturing or processing the data or the hosting provider. Providers should be listed in chronological order with the most recent provider being the last element of the list. | +| extent | [Extent Object](#extent-object) | **REQUIRED.** Spatial and temporal extents. | +| summaries | Map | STRONGLY RECOMMENDED. A map of property summaries, either a set of values or statistics such as a range. | +| links | \[[Link Object](#link-object)] | **REQUIRED.** A list of references to other documents. | +| assets | Map | Dictionary of asset objects that can be downloaded, each with a unique key. | + +### Additional Field Information + +#### stac_version + +In general, STAC versions can be mixed, but please keep the [recommended best practices](../best-practices.md#mixing-stac-versions) in mind. + +#### stac_extensions + +A list of extensions the Collection implements. +This list must only contain extensions that extend the Collection itself, see the the 'Scope' column in the list of +extensions. This does NOT declare the extensions of child Collection or Item +objects. The list contains URLs to the JSON Schema files it can be validated against. + +If an extension has influence on multiple parts +of the whole STAC structure, it must be listed in all affected parts (e.g. Collection and Item for the `datacube` extension). +If a structure, such as the summaries extension, provides fields in their JSON structure, these extensions must not be listed +here as they don't extend the Collection itself. For example, if a Collection includes the field `sat:platform` in the +summaries, the Collection should not list the `sat` extension in the `stac_extensions` field. + +#### id + +It is important that Collection identifiers are unique across the provider. And providers should strive as much as possible to make +their Collection ids 'globally' unique, prefixing any common information with a unique string. This could be the provider's name if +it is a fairly unique name, or their name combined with the domain they operate in. + +#### license + +Collection's license(s) as a SPDX [License identifier](https://spdx.org/licenses/). Alternatively, use `proprietary` (see below) if the license is not on the SPDX license list or `various` if multiple licenses apply. In all cases links to the license texts SHOULD be added, see the `license` link relation type. If no link to a license is included and the `license` field is set to `proprietary`, the Collection is private, and consumers have not been granted any explicit right to use the data. + +#### summaries + +Collections are *strongly recommended* to provide summaries of the values of fields that they can expect from the `properties` +of STAC Items contained in this Collection. This enables users to get a good sense of what the ranges and potential values of +different fields in the Collection are, without to inspect a number of Items (or crawl them exhaustively to get a definitive answer). +Summaries help to fully define Collections, especially if they don't link to any Items. They also give clients enough information to +build tailored user interfaces for querying the data, by presenting the potential values that are available. Summaries should summarize all values in every Item underneath the collection, including in any nested sub-Catalogs. + +A summary for a field can be specified in two ways: + +1. A set of all distinct values in an array: The set of values must contain at least one element and it is strongly recommended to list all values. If the field summarizes an array (e.g. [`instruments`](../item-spec/common-metadata.md#instrument)), the field's array elements of each Item must be merged to a single array with unique elements. +2. Statistics in a [Stats Object](#stats-object): Statistics by default only specify the range (minimum and maximum values), but can optionally be accompanied by additional statistical values. The range specified by the `minimum` and `maximum` properties can specify the potential range of values, but it is recommended to be as precise as possible. + +All values must follow the schema of the property they summarize. So the values in the array or the values given for `minimum` and `maxmimum` must comply to the original data type and any further restrictions that apply for the property they summarize. For example, the `minimum` for `gsd` can't be lower than zero and the summaries for `platform` and `instruments` must each be an array of strings (or alternatively minimum and maximum values, but that's not very meaningful). + +It is recommended to list as many properties as reasonable so that consumers get a full overview about the properties included in the Items. Nevertheless, it is not very useful to list all potential `title` values of the Items. Also, a range for the `datetime` property may be better suited to be included in the STAC Collection's `extent` field. In general, properties that are covered by the Collection specification should not be repeated in the summaries. + +See the [examples folder](../examples) for Collections with summaries to get a sense of how to use them. + +#### assets + +This provides an optional mechanism to expose assets that don't make sense at the Item level. +It is a dictionary of [Asset Objects](#asset-object) associated with the Collection that can be +downloaded or streamed, each with a unique key. +In general, the keys don't have any meaning and are considered to be non-descriptive unique identifiers. +Providers may assign any meaning to the keys for their respective use cases, but must not expect that clients understand them. +To communicate the purpose of an asset better use the `roles` field in the [Asset Object](#asset-object). +The definition provided here, at the Collection level, is the same as the +[Asset Object in Items](../item-spec/item-spec.md#asset-object). + +There are a few guidelines for using the asset construct at the Collection level: + +* Collection-level assets SHOULD NOT list any files also available in Items. +* If possible, item-level assets are always the preferable way to expose assets. + +Collection-level assets can be useful in some scenarios, for example: +1. Exposing additional data that applies Collection-wide and you don't want to expose it in each Item. This can be Collection-level metadata or a thumbnail for visualization purposes. +2. Individual Items can't properly be distinguished for some data structures, e.g. [Zarr](https://zarr.readthedocs.io/) as it's a data structure not contained in single files. +3. Exposing assets for "[Standalone Collections](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md#standalone-collections)". + +Oftentimes it is possible to model data and assets with either a Collection or an Item. In those scenarios we *recommend* to use +Items as much as is feasible, as they designed for assets. Using Collection-level assets should only be used if there is not another +option. + +### Extent Object + +The object describes the spatio-temporal extents of the Collection. Both spatial and temporal extents are required to be specified. + +| Element | Type | Description | +| -------- | ------------------------------------------------- | --------------------------------------------------------------------- | +| spatial | [Spatial Extent Object](#spatial-extent-object) | **REQUIRED.** Potential *spatial extents* covered by the Collection. | +| temporal | [Temporal Extent Object](#temporal-extent-object) | **REQUIRED.** Potential *temporal extents* covered by the Collection. | + +#### Spatial Extent Object + +The object describes the spatial extents of the Collection. + +| Element | Type | Description | +| ------- | ------------ | -------------------------------------------------------------------- | +| bbox | \[\[number]] | **REQUIRED.** Potential *spatial extents* covered by the Collection. | + +**bbox**: Bounding Boxes of the assets represented by this Collection using either 2D or 3D geometries. Each outer array element can be a separate bounding box, but it is recommended to only use multiple bounding boxes if a union of them would then include a large uncovered area (e.g. the union of Germany and Chile). + +The length of the inner array must be 2*n where n is the number of dimensions. The array contains all axes of the southwesterly most extent followed by all axes of the northeasterly most extent specified in Longitude/Latitude or Longitude/Latitude/Elevation based on [WGS 84](http://www.opengis.net/def/crs/OGC/1.3/CRS84). When using 3D geometries, the elevation of the southwesterly most extent is the minimum depth/height in meters and the elevation of the northeasterly most extent is the maximum. + +The coordinate reference system of the values is WGS 84 longitude/latitude. Example that covers the whole Earth: `[[-180.0, -90.0, 180.0, 90.0]]`. Example that covers the whole earth with a depth of 100 meters to a height of 150 meters: `[[-180.0, -90.0, -100.0, 180.0, 90.0, 150.0]]`. + +#### Temporal Extent Object + +The object describes the temporal extents of the Collection. + +| Element | Type | Description | +| -------- | ------------------ | --------------------------------------------------------------------- | +| interval | \[\[string\|null]] | **REQUIRED.** Potential *temporal extents* covered by the Collection. | + +**interval**: Each outer array element can be a separate temporal extent, but it is recommended to only use multiple temporal extents if a union of them would then include a large uncovered time span (e.g. only having data for the years 2000, 2010 and 2020). + +Each inner array consists of exactly two dates and times. Each date and time MUST be formatted according to [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6). The temporal reference system is the Gregorian calendar. + +Open date ranges are supported by setting either the start or the end time to `null`. Example for data from the beginning of 2019 until now: `[["2009-01-01T00:00:00Z", null]]`. + +### Provider Object + +The object provides information about a provider. A provider is any of the organizations that captures or processes the content of the Collection and therefore influences the data offered by this Collection. May also include information about the final storage provider hosting the data. + +| Field Name | Type | Description | +| ----------- | --------- | ------------------------------------------------------------ | +| name | string | **REQUIRED.** The name of the organization or the individual. | +| description | string | Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | +| roles | \[string] | Roles of the provider. Any of `licensor`, `producer`, `processor` or `host`. | +| url | string | Homepage on which the provider describes the dataset and publishes contact information. | + +**roles**: The provider's role(s) can be one or more of the following elements: + +* *licensor*: The organization that is licensing the dataset under the license specified in the Collection's `license` field. +* *producer*: The producer of the data is the provider that initially captured and processed the source data, e.g. ESA for Sentinel-2 data. +* *processor*: A processor is any provider who processed data to a derived product. +* *host*: The host is the actual provider offering the data on their storage. There should be no more than one host, specified as last element of the list. + +### Link Object + +This object describes a relationship with another entity. Data providers are advised to be liberal with links. + +| Field Name | Type | Description | +| ---------- | ------ | ------------------------------------------------------------ | +| href | string | **REQUIRED.** The actual link in the format of an URL. Relative and absolute links are both allowed. | +| rel | string | **REQUIRED.** Relationship between the current document and the linked document. See chapter "[Relation types](#relation-types)" for more information. | +| type | string | [Media type](../catalog-spec/catalog-spec.md#media-types) of the referenced entity. | +| title | string | A human readable title to be used in rendered displays of the link. | + +For a full discussion of the situations where relative and absolute links are recommended see the +['Use of links'](../best-practices.md#use-of-links) section of the STAC best practices. + +#### Relation types + +STAC Collections use a variety of `rel` types in the link object, to describe the exact nature of the link between this Collection and the entity it is linking to. +It is recommended to use the official [IANA Link Relation Types](https://www.iana.org/assignments/link-relations/link-relations.xhtml) where possible. +The following table explains places where custom STAC `rel` types are used for ollections. +This is done where there is not a clear official option, or where STAC uses an official type but adds additional meaning for the STAC context. + +| Type | Description | +| ------- | ------------------------------------------------------------ | +| self | STRONGLY RECOMMENDED. *Absolute* URL to the location that the Collection file can be found online, if available. This is particularly useful when in a download package that includes metadata, so that the downstream user can know where the data has come from. | +| root | URL to the root STAC Catalog or Collection. Collections should include a link to their root, even if it's the root and points to itself. | +| parent | URL to the parent STAC Catalog or Collection. Non-root Collections should include a link to their parent. | +| child | URL to a child STAC Catalog or Collection. | +| item | URL to a STAC Item. All Items linked from a Collection MUST refer back to its Collection with the [`collection` relation type](../item-spec/item-spec.md#relation-types). | +| license | The license URL(s) for the Collection SHOULD be specified if the `license` field is set to `proprietary` or `various`. If there is no public license URL available, it is RECOMMENDED to put the license text in a separate file and link to this file. | +| derived_from | URL to a STAC Collection that was used as input data in the creation of this Collection. See the note in [STAC Item](../item-spec/item-spec.md#derived_from) for more info. | + +A more complete list of possible `rel` types and their meaning in STAC can be found in the [Using Relation Types](../best-practices.md#using-relation-types) best practice. + +**Note:** The STAC Catalog specification requires a link to at least one `item` or `child` Catalog. This is *not* a requirement for Collections, but *recommended*. In contrast to Catalogs, it is **REQUIRED** that Items linked from a Collection MUST refer back to its Collection with the [`collection` relation type](../item-spec/item-spec.md#relation-types). + +### Asset Object + +An Asset is an object that contains a URI to data associated with the Collection that can be downloaded +or streamed. The definition provided here, at the Collection level, is the same as the +[Asset Object in Items](../item-spec/item-spec.md#asset-object). It is allowed to add additional fields. + +| Field Name | Type | Description | +| ----------- | --------- | ----------- | +| href | string | **REQUIRED.** URI to the asset object. Relative and absolute URI are both allowed. | +| title | string | The displayed title for clients and users. | +| description | string | A description of the Asset providing additional details, such as how it was processed or created. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | +| type | string | [Media type](../item-spec/item-spec.md#asset-media-type) of the asset. See the [common media types](../best-practices.md#common-media-types-in-stac) in the best practice doc for commonly used asset types. | +| roles | \[string] | The [semantic roles](../item-spec/item-spec.md#asset-role-types) of the asset, similar to the use of `rel` in links. | + +### Stats Object + +For a good understanding of the summarized field, statistics can be added. By default, only ranges with a minimum and a maximum value can be specified. +Ranges can be specified for [ordinal](https://en.wikipedia.org/wiki/Level_of_measurement#Ordinal_scale) values only, which means they need to have a rank order. +Therefore, ranges can only be specified for numbers and some special types of strings. Examples: grades (A to F), dates or times. +Implementors are free to add other derived statistical values to the object, for example `mean` or `stddev`. + +| Field Name | Type | Description | +| ---------- | -------------- | ----------- | +| minimum | number\|string | **REQUIRED.** Minimum value. | +| maximum | number\|string | **REQUIRED.** Maximum value. | + +## Media Type for STAC Collections + +A STAC Collection is a JSON file ([RFC 8259](https://tools.ietf.org/html/rfc8259)), and thus should use the +[`application/json`](https://tools.ietf.org/html/rfc8259#section-11) as the [Media Type](https://en.wikipedia.org/wiki/Media_type) +(previously known as the MIME Type). + +## Standalone Collections + +STAC Collections which don't link to any Item are called **standalone Collections**. +To describe them with more fields than the Collection fields has to offer, it is allowed to re-use the metadata fields defined by extensions for Items in the `summaries` field. +This makes much sense for fields such as `platform` or `proj:epsg`, which are often the same for a whole Collection, but doesn't make much sense for `eo:cloud_cover`, which usually varies heavily across a Collection. +The data provider is free to decide, which fields are reasonable to be used. diff --git a/collection-spec/json-schema/collection.json b/collection-spec/json-schema/collection.json new file mode 100644 index 00000000..422385f2 --- /dev/null +++ b/collection-spec/json-schema/collection.json @@ -0,0 +1,170 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/collection-spec/json-schema/collection.json#", + "title": "STAC Collection Specification", + "description": "This object represents Collections in a SpatioTemporal Asset Catalog.", + "allOf": [ + { + "$ref": "../../catalog-spec/json-schema/catalog-core.json" + }, + { + "$ref": "#/definitions/collection" + } + ], + "definitions": { + "collection": { + "title": "STAC Collection", + "description": "These are the fields specific to a STAC Collection. All other fields are inherited from STAC Catalog.", + "type": "object", + "required": [ + "type", + "license", + "extent" + ], + "properties": { + "type": { + "title": "Type of STAC entity", + "const": "Collection" + }, + "stac_extensions": { + "title": "STAC extensions", + "type": "array", + "uniqueItems": true, + "items": { + "anyOf": [ + { + "title": "Reference to a JSON Schema", + "type": "string", + "format": "iri" + }, + { + "title": "Reference to a core extension", + "type": "string" + } + ] + } + }, + "keywords": { + "title": "Keywords", + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "title": "Collection License Name", + "type": "string", + "pattern": "^[\\w\\-\\.\\+]+$" + }, + "providers": { + "type": "array", + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "title": "Organization name", + "type": "string" + }, + "description": { + "title": "Organization description", + "type": "string" + }, + "roles": { + "title": "Organization roles", + "type": "array", + "items": { + "type": "string", + "enum": [ + "producer", + "licensor", + "processor", + "host" + ] + } + }, + "url": { + "title": "Organization homepage", + "type": "string", + "format": "iri" + } + } + } + }, + "extent": { + "title": "Extents", + "type": "object", + "required": [ + "spatial", + "temporal" + ], + "properties": { + "spatial": { + "title": "Spatial extent object", + "type": "object", + "required": [ + "bbox" + ], + "properties": { + "bbox": { + "title": "Spatial extents", + "type": "array", + "minItems": 1, + "items": { + "title": "Spatial extent", + "type": "array", + "oneOf": [ + { + "minItems":4, + "maxItems":4 + }, + { + "minItems":6, + "maxItems":6 + } + ], + "items": { + "type": "number" + } + } + } + } + }, + "temporal": { + "title": "Temporal extent object", + "type": "object", + "required": [ + "interval" + ], + "properties": { + "interval": { + "title": "Temporal extents", + "type": "array", + "minItems": 1, + "items": { + "title": "Temporal extent", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": [ + "string", + "null" + ], + "format": "date-time" + } + } + } + } + } + } + }, + "assets": { + "$ref": "../../item-spec/json-schema/item.json#/definitions/assets" + } + } + } + } +} \ No newline at end of file diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..85b5f5a1 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,89 @@ +# STAC Examples + +This directory contains various examples for all parts of the STAC specification. It is structured to be two valid STACs, meaning both [catalog.json](catalog.json) and [collection.json](collection.json) should successfully load in various tools. They do not follow *all* the [best practices](../best-practices.md) for STAC, mostly +due to the fact that they contrive examples to show the spec and we are hosting in GitHub. But we note below where they differ from an ideal catalog. + +The various fields are mostly fictional, to be able to demonstrate the various aspects of the spec as tersely as possible. To get a sense +of real world STAC implementations we recommend exploring the [stac-examples](http://github.com/stac-utils/stac-examples) repo, which +gathers in one place copies of STAC [Items](../item-spec/item-spec.md) and [Collection](../collection-spec/collection-spec.md) +from a number of different production catalogs that all follow good STAC practices. And you should also explore the various catalogs +listed on [STAC Index](http://stacindex.org), to see full catalogs in production. + +## Organization + +This directory contains two STAC implementations, both valid, but simplified a bit to be illustrative of the key concepts, so +they do not quite follow all the best practices. + +### Simple Collection + +This STAC implementation consists of three files, all contained at the root of the examples directory + +**[collection.json](collection.json)** is a minimal 'simple collection', that links to three items. + +**[simple-item.json](simple-item.json)** is the most minimal possible compliant Item record. Most all data will +include additional fields, as STAC is designed to be a minimal common subset. But it is useful for showing exactly what is +required. + +**[core-item.json](core-item.json)** is a more realistic example, for a hypothetical analytic image +acquisition from a satellite company called 'Remote Data'. It includes additional fields covering the [common +metadata](../item-spec/common-metadata.md). It also links to a variety of assets that is typical for +satellite imagery, as most providers include a number of complementary files. + +**[extended-item.json](extended-item.json)** is arguably an even more realistic example, as it includes a number of the +[extensions](../extensions/) that are commonly used, to demonstrate how implementations tend to start with the core, and add in +a number of the core extensions. + +**[collectionless-item.json](collectionless-item.json)** demonstrates the common metadata that is only used when an Item does not have +a collection. It is recommended to organize items in collections, but we wanted to show how this works. This is not technically in the +'simple collection' of this section, but it follows the same pattern, so is included here. + +### Nested Catalog + +This STAC implementation shows a common pattern, starting with a catalog that links to a number of distinct collections, which may +link down to a number of items. + +**[catalog.json](catalog.json)** is a minimal catalog implementation, linking to two other collections. + +**[collection-only/collection.json](collection-only/collection.json)** is a collection that does not link to any items. This +demonstrates how is is possible to make use of STAC Collections without needing items, to serve as nice summarizing metadata for +tools that work with full layers / collections. This example collection is based on real Sentinel-2 values, so is not quite fictional, +but should be taken as just an example. + +**[extensions-collection/collection.json](extensions-collection/collection.json)** contains a small number of items, that demonstrate +more functionality available in STAC [extensions](../extensions/). These are linked to directly from the individual extensions. These +items follow the recommendations for [Catalog Layout Best Practices](../best-practices.md#catalog-layout). + +## In Depth + +As mentioned above, the files in this examples directory form valid STAC implementations. They are all based on a +fictional remote sensing company called 'Remote Data', with a URL at remotedata.io. This domain has not been set up, so those links +will not work, but any valid data provider should provide valid links to their homepage. + +The examples use the `rd:` prefix to show how providers can use custom fields when there are not set fields. In the examples these +do not link to a schema which is completely valid, but it is recommended that providers do write a JSON schema that can validate +their custom fields (we will work to add an example schema for the `rd:` fields in the future). + +### Catalog Type + +One of the most important STAC Best Practices is to [use links consistently](../best-practices.md#use-of-links), following one of the +described 'catalog types'. The catalogs described here are [Relative Published Catalogs](../best-practices.md#relative-published-catalog), +that use absolute URL's to refer to their assets (so would be an example of a [Self-contained Metadata +Only](../best-practices.md#self-contained-metadata-only) catalog that is published). + +### Differences with STAC Best Practices + +One of the most important documents in this repository is the one about [best practices](../best-practices.md). It describes a number +of practical recommendations gained by people actually implementing STAC. The core spec is designed to be as flexible as possible, so +that it is not too rigid and unable to handle unanticipated needs. But we recommend following as many of the best practices as is +feasible, as it will help ensure various STAC tools work much better. The examples in this folder don't align with all the best +practices, mostly because they are meant to demonstrate things as tersely as possible, and also because they live directly inside +a github repository. As many people will look at these examples and take them as 'how things should be' we felt its important to +highlight where things here differ from the actual best practices. + +#### Catalog Layout + +Another important recommendations concerns the [layout of STAC catalogs](../best-practices.md#catalog-layout). This is important +for tools to be able to expect a certain layout, and most tools will follow the described layout. The simple collection that consists +of the collection.json and its 3 linked items violates this. This is done to be able to show item examples directly in the root of +the 'examples' folder, so people don't have to dig deep into folders to get a quick example. But a proper catalog layout would +put the items in sub-directories, along with their assets. diff --git a/examples/catalog.json b/examples/catalog.json new file mode 100644 index 00000000..1bac09f9 --- /dev/null +++ b/examples/catalog.json @@ -0,0 +1,30 @@ +{ + "id": "examples", + "type": "Catalog", + "stac_version": "1.0.0-rc.2", + "description": "This catalog is a simple demonstration of an example catalog that is used to organize a hierarchy of collections and their items.", + "links": [ + { + "rel": "root", + "href": "./catalog.json", + "type": "application/json" + }, + { + "rel": "child", + "href": "./extensions-collection/collection.json", + "type": "application/json", + "title": "Collection Demonstrating STAC Extensions" + }, + { + "rel": "child", + "href": "./collection-only/collection.json", + "type": "application/json", + "title": "Collection with no items (standalone)" + }, + { + "rel": "self", + "href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0-rc.2/examples/catalog.json", + "type": "application/json" + } + ] +} diff --git a/examples/collection-only/collection.json b/examples/collection-only/collection.json new file mode 100644 index 00000000..9a8da7c3 --- /dev/null +++ b/examples/collection-only/collection.json @@ -0,0 +1,228 @@ +{ + "type": "Collection", + "stac_version": "1.0.0-rc.2", + "stac_extensions": [], + "id": "sentinel-2", + "title": "Sentinel-2 MSI: MultiSpectral Instrument, Level-1C", + "description": "Sentinel-2 is a wide-swath, high-resolution, multi-spectral\nimaging mission supporting Copernicus Land Monitoring studies,\nincluding the monitoring of vegetation, soil and water cover,\nas well as observation of inland waterways and coastal areas.\n\nThe Sentinel-2 data contain 13 UINT16 spectral bands representing\nTOA reflectance scaled by 10000. See the [Sentinel-2 User Handbook](https://sentinel.esa.int/documents/247904/685211/Sentinel-2_User_Handbook)\nfor details. In addition, three QA bands are present where one\n(QA60) is a bitmask band with cloud mask information. For more\ndetails, [see the full explanation of how cloud masks are computed.](https://sentinel.esa.int/web/sentinel/technical-guides/sentinel-2-msi/level-1c/cloud-masks)\n\nEach Sentinel-2 product (zip archive) may contain multiple\ngranules. Each granule becomes a separate Earth Engine asset.\nEE asset ids for Sentinel-2 assets have the following format:\nCOPERNICUS/S2/20151128T002653_20151128T102149_T56MNN. Here the\nfirst numeric part represents the sensing date and time, the\nsecond numeric part represents the product generation date and\ntime, and the final 6-character string is a unique granule identifier\nindicating its UTM grid reference (see [MGRS](https://en.wikipedia.org/wiki/Military_Grid_Reference_System)).\n\nFor more details on Sentinel-2 radiometric resoltuon, [see this page](https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/resolutions/radiometric).\n", + "license": "proprietary", + "keywords": [ + "copernicus", + "esa", + "eu", + "msi", + "radiance", + "sentinel" + ], + "providers": [ + { + "name": "European Union/ESA/Copernicus", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2015-06-23T00:00:00Z", + null + ] + ] + } + }, + "assets": { + "metadata_iso_19139": { + "roles": [ + "metadata", + "iso-19139" + ], + "href": "https://storage.googleapis.com/open-cogs/stac-examples/sentinel-2-iso-19139.xml", + "title": "ISO 19139 metadata", + "type": "application/vnd.iso.19139+xml" + } + }, + "summaries": { + "datetime": { + "minimum": "2015-06-23T00:00:00Z", + "maximum": "2019-07-10T13:44:56Z" + }, + "platform": [ + "sentinel-2a", + "sentinel-2b" + ], + "constellation": [ + "sentinel-2" + ], + "instruments": [ + "msi" + ], + "view:off_nadir": { + "minimum": 0, + "maximum": 100 + }, + "view:sun_elevation": { + "minimum": 6.78, + "maximum": 89.9 + }, + "sci:citation": [ + "Copernicus Sentinel data [Year]" + ], + "gsd": [ + 10, + 30, + 60 + ], + "proj:epsg": [ + 32601, + 32602, + 32603, + 32604, + 32605, + 32606, + 32607, + 32608, + 32609, + 32610, + 32611, + 32612, + 32613, + 32614, + 32615, + 32616, + 32617, + 32618, + 32619, + 32620, + 32621, + 32622, + 32623, + 32624, + 32625, + 32626, + 32627, + 32628, + 32629, + 32630, + 32631, + 32632, + 32633, + 32634, + 32635, + 32636, + 32637, + 32638, + 32639, + 32640, + 32641, + 32642, + 32643, + 32644, + 32645, + 32646, + 32647, + 32648, + 32649, + 32650, + 32651, + 32652, + 32653, + 32654, + 32655, + 32656, + 32657, + 32658, + 32659, + 32660 + ], + "eo:bands": [ + { + "name": "B1", + "common_name": "coastal", + "center_wavelength": 4.439 + }, + { + "name": "B2", + "common_name": "blue", + "center_wavelength": 4.966 + }, + { + "name": "B3", + "common_name": "green", + "center_wavelength": 5.6 + }, + { + "name": "B4", + "common_name": "red", + "center_wavelength": 6.645 + }, + { + "name": "B5", + "center_wavelength": 7.039 + }, + { + "name": "B6", + "center_wavelength": 7.402 + }, + { + "name": "B7", + "center_wavelength": 7.825 + }, + { + "name": "B8", + "common_name": "nir", + "center_wavelength": 8.351 + }, + { + "name": "B8A", + "center_wavelength": 8.648 + }, + { + "name": "B9", + "center_wavelength": 9.45 + }, + { + "name": "B10", + "center_wavelength": 1.3735 + }, + { + "name": "B11", + "common_name": "swir16", + "center_wavelength": 1.6137 + }, + { + "name": "B12", + "common_name": "swir22", + "center_wavelength": 2.2024 + } + ] + }, + "links": [ + { + "rel": "parent", + "href": "../catalog.json" + }, + { + "rel": "root", + "href": "../catalog.json" + }, + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", + "title": "Legal notice on the use of Copernicus Sentinel Data and Service Information" + } + ] +} diff --git a/examples/collection.json b/examples/collection.json new file mode 100644 index 00000000..4fadb641 --- /dev/null +++ b/examples/collection.json @@ -0,0 +1,93 @@ +{ + "id": "simple-collection", + "type": "Collection", + "stac_version": "1.0.0-rc.2", + "description": "A simple collection demonstrating core catalog fields with links to a couple of items", + "title": "Simple Example Collection", + "providers": [ + { + "name": "Remote Data, Inc", + "description": "Producers of awesome spatiotemporal assets", + "roles": [ + "producer", + "processor" + ], + "url": "http://remotedata.io" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + 172.911, + 1.343, + 172.955, + 1.3691 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2020-12-11T09:06:43.312000Z", + "2020-12-14T18:02:31.437000Z" + ] + ] + } + }, + "license": "CC-BY-4.0", + "summaries": { + "platform": [ + "cool_sat2", + "cool_sat1" + ], + "constellation": [ + "ion" + ], + "instruments": [ + "cool_sensor_v1" + ], + "gsd": { + "minimum": 0.512, + "maximum": 0.7 + }, + "view:off_nadir": { + "minimum": 0, + "maximum": 15 + }, + "view:sun_elevation": { + "minimum": 6.78, + "maximum": 40 + } + }, + "links": [ + { + "rel": "root", + "href": "./collection.json", + "type": "application/json" + }, + { + "rel": "item", + "href": "./simple-item.json", + "type": "application/geo+json", + "title": "Simple Item" + }, + { + "rel": "item", + "href": "./core-item.json", + "type": "application/geo+json", + "title": "Core Item" + }, + { + "rel": "item", + "href": "./extended-item.json", + "type": "application/geo+json", + "title": "Extended Item" + }, + { + "rel": "self", + "href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0-rc.2/examples/collection.json", + "type": "application/json" + } + ] +} diff --git a/examples/collectionless-item.json b/examples/collectionless-item.json new file mode 100644 index 00000000..250bb704 --- /dev/null +++ b/examples/collectionless-item.json @@ -0,0 +1,147 @@ +{ + "stac_version": "1.0.0-rc.2", + "stac_extensions": [ + "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/view/v1.0.0/schema.json" + ], + "type": "Feature", + "id": "CS3-20160503_132131_08", + "bbox": [ + -122.59750209, + 37.48803556, + -122.2880486, + 37.613537207 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.308150179, + 37.488035566 + ], + [ + -122.597502109, + 37.538869539 + ], + [ + -122.576687533, + 37.613537207 + ], + [ + -122.2880486, + 37.562818007 + ], + [ + -122.308150179, + 37.488035566 + ] + ] + ] + }, + "properties": { + "title": "Full Item", + "description": "A sample STAC Item demonstrates an Item that does not have a collection, which is not recommended, but allowed by the spec.", + "datetime": null, + "start_datetime": "2016-05-03T13:22:30Z", + "end_datetime": "2016-05-03T13:27:30Z", + "created": "2016-05-04T00:00:01Z", + "updated": "2017-01-01T00:30:55Z", + "license": "various", + "providers": [ + { + "name": "Remote Data, Inc", + "description": "Producers of awesome spatiotemporal assets", + "roles": [ + "producer", + "processor" + ], + "url": "http://remotedata.it" + } + ], + "platform": "cool_sat2", + "instruments": [ + "cool_sensor_v1" + ], + "view:sun_elevation": 33.4, + "gsd": 0.512, + "cs:type": "scene", + "cs:anomalous_pixels": 0.14, + "cs:earth_sun_distance": 1.014156, + "cs:sat_id": "CS3", + "cs:product_level": "LV1B" + }, + "collection": "CS3", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json" + }, + { + "rel": "alternate", + "type": "text/html", + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.html" + }, + { + "rel": "license", + "type": "text/html", + "href": "http://remotedata.io/license.html" + } + ], + "assets": { + "analytic": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/analytic.tif", + "title": "4-Band Analytic", + "eo:bands": [ + { + "name": "band1" + }, + { + "name": "band1" + }, + { + "name": "band2" + }, + { + "name": "band3" + } + ] + }, + "thumbnail": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/thumbnail.png", + "title": "Thumbnail", + "type": "image/png", + "roles": [ + "thumbnail" + ] + }, + "udm": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/UDM.tif", + "title": "Unusable Data Mask" + }, + "json-metadata": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/extended-metadata.json", + "title": "Extended Metadata", + "type": "application/json", + "roles": [ + "metadata" + ] + }, + "ephemeris": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/S3-20160503_132130_04.EPH", + "title": "Satellite Ephemeris Metadata" + } + } +} diff --git a/examples/core-item.json b/examples/core-item.json new file mode 100644 index 00000000..0b453dd4 --- /dev/null +++ b/examples/core-item.json @@ -0,0 +1,117 @@ +{ + "stac_version": "1.0.0-rc.2", + "stac_extensions": [], + "type": "Feature", + "id": "20201211_223832_CS2", + "bbox": [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 172.91173669923782, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3438851951615003 + ] + ] + ] + }, + "properties": { + "title": "Core Item", + "description": "A sample STAC Item that includes examples of all common metadata", + "datetime": null, + "start_datetime": "2020-12-11T22:38:32.125Z", + "end_datetime": "2020-12-11T22:38:32.327Z", + "created": "2020-12-12T01:48:13.725Z", + "updated": "2020-12-12T01:48:13.725Z", + "platform": "cool_sat2", + "instruments": [ + "cool_sensor_v1" + ], + "constellation": "ion", + "mission": "collection 5624", + "gsd": 0.512 + }, + "collection": "simple-collection", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json" + }, + { + "rel": "alternate", + "type": "text/html", + "href": "http://remotedata.io/catalog/20201211_223832_CS2/index.html" + } + ], + "assets": { + "analytic": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "4-Band Analytic", + "roles": [ + "data" + ] + }, + "thumbnail": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "title": "Thumbnail", + "type": "image/png", + "roles": [ + "thumbnail" + ] + }, + "visual": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "3-Band Visual", + "roles": [ + "visual" + ] + }, + "udm": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif", + "title": "Unusable Data Mask", + "type": "image/tiff; application=geotiff;" + }, + "json-metadata": { + "href": "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json", + "title": "Extended Metadata", + "type": "application/json", + "roles": [ + "metadata" + ] + }, + "ephemeris": { + "href": "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH", + "title": "Satellite Ephemeris Metadata" + } + } +} diff --git a/examples/extended-item.json b/examples/extended-item.json new file mode 100644 index 00000000..4012cb4a --- /dev/null +++ b/examples/extended-item.json @@ -0,0 +1,191 @@ +{ + "stac_version": "1.0.0-rc.2", + "stac_extensions": [ + "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/projection/v1.0.0/schema.json", + "https://stac-extensions.github.io/scientific/v1.0.0/schema.json", + "https://stac-extensions.github.io/view/v1.0.0/schema.json", + "https://stac-extensions.github.io/remote-data/v1.0.0/schema.json" + ], + "type": "Feature", + "id": "20201211_223832_CS2", + "bbox": [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 172.91173669923782, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3438851951615003 + ] + ] + ] + }, + "properties": { + "title": "Extended Item", + "description": "A sample STAC Item that includes a variety of examples from the stable extensions", + "datetime": "2020-12-11T22:38:32.125Z", + "created": "2020-12-12T01:48:13.725Z", + "updated": "2020-12-12T01:48:13.725Z", + "platform": "cool_sat2", + "instruments": [ + "cool_sensor_v1" + ], + "gsd": 0.66, + "eo:cloud_cover": 1.2, + "proj:epsg": 32659, + "proj:shape": [ + 5558, + 9559 + ], + "proj:transform": [ + 0.5, + 0, + 712710, + 0, + -0.5, + 151406, + 0, + 0, + 1 + ], + "view:sun_elevation": 54.9, + "view:off_nadir": 3.8, + "view:sun_azimuth": 135.7, + "rd:type": "scene", + "rd:anomalous_pixels": 0.14, + "rd:earth_sun_distance": 1.014156, + "rd:sat_id": "cool_sat2", + "rd:product_level": "LV3A", + "sci:doi": "10.5061/dryad.s2v81.2/27.2" + }, + "collection": "simple-collection", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json" + }, + { + "rel": "alternate", + "type": "text/html", + "href": "http://remotedata.io/catalog/20201211_223832_CS2/index.html" + } + ], + "assets": { + "analytic": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "4-Band Analytic", + "roles": [ + "data" + ], + "eo:bands": [ + { + "name": "band1", + "common_name": "blue", + "center_wavelength": 470, + "full_width_half_max": 70 + }, + { + "name": "band2", + "common_name": "green", + "center_wavelength": 560, + "full_width_half_max": 80 + }, + { + "name": "band3", + "common_name": "red", + "center_wavelength": 645, + "full_width_half_max": 90 + }, + { + "name": "band4", + "common_name": "nir", + "center_wavelength": 800, + "full_width_half_max": 152 + } + ] + }, + "thumbnail": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "title": "Thumbnail", + "type": "image/png", + "roles": [ + "thumbnail" + ] + }, + "visual": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "3-Band Visual", + "roles": [ + "visual" + ], + "eo:bands": [ + { + "name": "band3", + "common_name": "red", + "center_wavelength": 645, + "full_width_half_max": 90 + }, + { + "name": "band2", + "common_name": "green", + "center_wavelength": 560, + "full_width_half_max": 80 + }, + { + "name": "band1", + "common_name": "blue", + "center_wavelength": 470, + "full_width_half_max": 70 + } + ] + }, + "udm": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif", + "title": "Unusable Data Mask", + "type": "image/tiff; application=geotiff;" + }, + "json-metadata": { + "href": "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json", + "title": "Extended Metadata", + "type": "application/json", + "roles": [ + "metadata" + ] + }, + "ephemeris": { + "href": "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH", + "title": "Satellite Ephemeris Metadata" + } + } +} diff --git a/examples/extensions-collection/collection.json b/examples/extensions-collection/collection.json new file mode 100644 index 00000000..a79fabe3 --- /dev/null +++ b/examples/extensions-collection/collection.json @@ -0,0 +1,66 @@ +{ + "id": "extensions-collection", + "type": "Collection", + "stac_version": "1.0.0-rc.2", + "description": "A heterogenous collection containing deeper examples of various extensions", + "links": [ + { + "rel": "root", + "href": "../catalog.json", + "type": "application/json" + }, + { + "rel": "item", + "href": "./proj-example/proj-example.json", + "title": "Proj extension example" + }, + { + "rel": "license", + "href": "https://remotedata.io/license.html", + "title": "Remote Data License Terms" + }, + { + "rel": "parent", + "href": "../catalog.json", + "type": "application/json" + } + ], + "stac_extensions": [], + "title": "Collection of Extension Items", + "keywords": [ + "examples", + "sar", + "projection" + ], + "providers": [ + { + "name": "Remote Data, Inc.", + "roles": [ + "producer", + "licensor" + ], + "url": "https://remotedata.io" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2009-05-20T02:40:01.042784Z", + "2018-11-03T23:59:55.112875Z" + ] + ] + } + }, + "license": "PDDL-1.0" +} diff --git a/examples/extensions-collection/proj-example/proj-example.json b/examples/extensions-collection/proj-example/proj-example.json new file mode 100644 index 00000000..91fa8130 --- /dev/null +++ b/examples/extensions-collection/proj-example/proj-example.json @@ -0,0 +1,278 @@ +{ + "type": "Feature", + "stac_version": "1.0.0-rc.2", + "id": "proj-example", + "properties": { + "datetime": "2018-10-01T01:08:32.033000Z", + "proj:epsg": 32614, + "proj:wkt2": "PROJCS[\"WGS 84 / UTM zone 14N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-99],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"32614\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]", + "proj:projjson": { + "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", + "type": "ProjectedCRS", + "name": "WGS 84 / UTM zone 14N", + "base_crs": { + "name": "WGS 84", + "datum": { + "type": "GeodeticReferenceFrame", + "name": "World Geodetic System 1984", + "ellipsoid": { + "name": "WGS 84", + "semi_major_axis": 6378137, + "inverse_flattening": 298.257223563 + } + }, + "coordinate_system": { + "subtype": "ellipsoidal", + "axis": [ + { + "name": "Geodetic latitude", + "abbreviation": "Lat", + "direction": "north", + "unit": "degree" + }, + { + "name": "Geodetic longitude", + "abbreviation": "Lon", + "direction": "east", + "unit": "degree" + } + ] + }, + "id": { + "authority": "EPSG", + "code": 4326 + } + }, + "conversion": { + "name": "UTM zone 14N", + "method": { + "name": "Transverse Mercator", + "id": { + "authority": "EPSG", + "code": 9807 + } + }, + "parameters": [ + { + "name": "Latitude of natural origin", + "value": 0, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8801 + } + }, + { + "name": "Longitude of natural origin", + "value": -99, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8802 + } + }, + { + "name": "Scale factor at natural origin", + "value": 0.9996, + "unit": "unity", + "id": { + "authority": "EPSG", + "code": 8805 + } + }, + { + "name": "False easting", + "value": 500000, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8806 + } + }, + { + "name": "False northing", + "value": 0, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8807 + } + } + ] + }, + "coordinate_system": { + "subtype": "Cartesian", + "axis": [ + { + "name": "Easting", + "abbreviation": "E", + "direction": "east", + "unit": "metre" + }, + { + "name": "Northing", + "abbreviation": "N", + "direction": "north", + "unit": "metre" + } + ] + }, + "area": "World - N hemisphere - 102°W to 96°W - by country", + "bbox": { + "south_latitude": 0, + "west_longitude": -102, + "north_latitude": 84, + "east_longitude": -96 + }, + "id": { + "authority": "EPSG", + "code": 32614 + } + }, + "proj:geometry": { + "coordinates": [ + [ + [ + 169200, + 3712800 + ], + [ + 403200, + 3712800 + ], + [ + 403200, + 3951000 + ], + [ + 169200, + 3951000 + ], + [ + 169200, + 3712800 + ] + ] + ], + "type": "Polygon" + }, + "proj:bbox": [ + 169200, + 3712800, + 403200, + 3951000 + ], + "proj:centroid": { + "lat": 34.595302781575604, + "lon": -101.34448382627504 + }, + "proj:shape": [ + 8391, + 8311 + ], + "proj:transform": [ + 30, + 0, + 224985, + 0, + -30, + 6790215, + 0, + 0, + 1 + ] + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 152.52758, + 60.63437 + ], + [ + 149.1755, + 61.19016 + ], + [ + 148.13933, + 59.51584 + ], + [ + 151.33786, + 58.97792 + ], + [ + 152.52758, + 60.63437 + ] + ] + ] + }, + "links": [ + { + "rel": "root", + "href": "../../catalog.json", + "type": "application/json" + }, + { + "rel": "parent", + "href": "../collection.json", + "type": "application/json" + } + ], + "assets": { + "B1": { + "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B1.TIF", + "type": "image/tiff; application=geotiff", + "title": "Band 1 (coastal)", + "eo:bands": [ + { + "name": "B1", + "common_name": "coastal", + "center_wavelength": 0.44, + "full_width_half_max": 0.02 + } + ] + }, + "B8": { + "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B8.TIF", + "type": "image/tiff; application=geotiff", + "title": "Band 8 (panchromatic)", + "eo:bands": [ + { + "name": "B8", + "common_name": "panchromatic", + "center_wavelength": 0.59, + "full_width_half_max": 0.18 + } + ], + "proj:shape": [ + 16781, + 16621 + ], + "proj:transform": [ + 15, + 0, + 224992.5, + 0, + -15, + 6790207.5, + 0, + 0, + 1 + ] + } + }, + "bbox": [ + 148.13933, + 59.51584, + 152.52758, + 60.63437 + ], + "stac_extensions": [ + "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/projection/v1.0.0/schema.json" + ], + "collection": "landsat-8-l1" +} diff --git a/examples/simple-item.json b/examples/simple-item.json new file mode 100644 index 00000000..ad4d526d --- /dev/null +++ b/examples/simple-item.json @@ -0,0 +1,74 @@ +{ + "stac_version": "1.0.0-rc.2", + "stac_extensions": [], + "type": "Feature", + "id": "20201211_223832_CS2", + "bbox": [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 172.91173669923782, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3438851951615003 + ] + ] + ] + }, + "properties": { + "datetime": "2020-12-11T22:38:32.125000Z" + }, + "collection": "simple-collection", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json" + } + ], + "assets": { + "visual": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "3-Band Visual", + "roles": [ + "visual" + ] + }, + "thumbnail": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "title": "Thumbnail", + "type": "image/jpeg", + "roles": [ + "thumbnail" + ] + } + } +} diff --git a/extensions/README.md b/extensions/README.md new file mode 100644 index 00000000..e864f3ce --- /dev/null +++ b/extensions/README.md @@ -0,0 +1,172 @@ +# Extensions + +- [Overview](#overview) +- [General Conventions](#general-conventions) +- [Stable STAC Extensions](#stable-stac-extensions) +- [Community Extensions](#community-extensions) + - [Extension Maturity](#extension-maturity) + - [Proposed extensions](#proposed-extensions) +- [Extending STAC](#extending-stac) + - [Proposing new extensions](#proposing-new-extensions) + - [Prefixes](#prefixes) + - [Use of arrays and objects](#use-of-arrays-and-objects) + +## Overview + +One of the most important aspects of the SpatioTemporal Asset Catalog specification is its extensibility. The core +STAC specification defines only a minimal core, but is designed for extension. It is expected that most real-world +implementations will use several 'extensions' to fully describe their data. This document describes how extensions +work, and links to the 'core' extensions included in this repo, as well as to a variety of 'community' extensions. + +**For the complete list of available extensions see the [STAC extensions overview page](https://stac-extensions.github.io/).** + +Extensions to the core STAC specification provide additional JSON fields that can be used to better describe +the data. Most tend to be about describing a particular domain or type of data, but some imply +functionality. + +Extensions include a JSON Schema precisely describing the structure, a natural language description of the fields, and thorough examples. + +Anybody can create an extension for their data, and data providers often work together to share +fields between them to create a shared community extensions. See the section below on '[Extending STAC](#extending-stac)') +for information on how to get started. And everyone is encouraged to link to the extension in the table below, so others +can be aware of it. + +Each extension has at least one *owner*. You can find extension owners in each extension's README. + +## General Conventions + +1. Additional attributes relating to an [Item](../item-spec/item-spec.md) should be added into the Item Properties object, rather than directly in the Item object. +2. In general, additional attributes that apply to an Item Asset should also be allowed in Item Properties and vice-versa. +For example, the `eo:bands` attribute may be used in Item Properties to describe the aggregation of all bands available in +the Item Asset objects contained in the Item, but may also be used in an individual Item Asset to describe only the bands available in that asset. +3. Additional attributes relating to a [Catalog](../catalog-spec/catalog-spec.md) or [Collection](../collection-spec/collection-spec.md) should be added to the root of the object. + +## Stable STAC Extensions + +These extensions are considered stable and are widely used in many production implementations. As additional extensions advance +through the [Extension Maturity](#extension-maturity) classification they, will be added here. + +| Extension Title | Description | +|-----------------------------------------------------------------------|--------------------------------| +| [Electro-Optical](https://github.com/stac-extensions/eo/) | Covers electro-optical data that represents a snapshot of the Earth for a single date and time. It could consist of multiple spectral bands, for example visible bands, infrared bands, red edge bands and panchromatic bands. The extension provides common fields like bands, cloud cover, gsd and more. | +| [Projection](https://github.com/stac-extensions/projection/) | Provides a way to describe Items whose assets are in a geospatial projection. | +| [Scientific Citation](https://github.com/stac-extensions/scientific/) | Metadata that indicate from which publication data originates and how the data itself should be cited or referenced. | +| [View Geometry](https://github.com/stac-extensions/view/) | View Geometry adds metadata related to angles of sensors and other radiance angles that affect the view of resulting data | + +## Community Extensions + +There are many more extensions that are part of the broader STAC ecosystem. The center of activity for these is the +[stac-extensions GitHub organization](https://github.com/stac-extensions), which has a number of extension repositories. For +an overview of all extensions with their [Extension Maturity](#extension-maturity) classification see the +[STAC extensions overview page](https://stac-extensions.github.io/). + +### Proposed extensions + +Beyond the community extensions there have been a number of extensions that people have proposed to the STAC community. These +can be found in the STAC [Issue Tracker](https://github.com/radiantearth/stac-spec/issues) under the +[new extension](https://github.com/radiantearth/stac-spec/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+extension%22) label. +These are ideas that others would likely use and potentially collaborate on. Anyone is free to add new +ideas there, and see the section below on [proposing new extensions](#proposing-new-extensions) for the +workflow to advance ideas into full-fledged community extensions. + +## Extending STAC + +Anyone is welcome to create an extension. There are several types of extensions, some just add additional fields, +some change the behavior of STAC and some introduce completely new functionality. New extensions should try to align +with existing extensions as well as possible and may even re-use fields and their definitions until they may get split +into a new extension that combines commonly used fields across multiple extensions. +Best practices for extension proposals are still emerging in this section. + +### Proposing new extensions + +Extensions can be hosted anywhere, but should use the [extension template](https://github.com/stac-extensions/stac-extensions.github.io#using-the-stac-extensions-template) +as a starting point. If you'd like to add a repository to the [stac-extensions](https://github.com/stac-extensions) +GitHub organization, just ask on [Gitter](https://gitter.im/SpatioTemporal-Asset-Catalog/Lobby)! This is fine for +work-in-progress extensions. You can also host the extension repository in your own GitHub account, and optionally +transfer it to the stac-extensions org later. + +For new extensions that require community discussion, we recommend the following workflow: + +- Use the stac-extensions template to sketch out your proposed extension +- Open an issue on this repository with the prefix "New Extension: " and describe the extension. Include a link to the extension repository. +- Discussion can occur on that issue, or discussion can move to issues/pull requests on the extension repository directly. +- Once the extension has an initial release, the issue on stac-spec will be closed. + +### Extension Maturity + +There are many extensions being built with STAC, but they have varying degrees of maturity. All community extensions +listed here included must include a maturity classification, so that STAC spec users can easily get a sense of how +much they can count on the extension. Extension creators are encouraged to list their extensions here, even if it is just +an rough proposal, so others can potentially collaborate. + +| Maturity Classification | Min Impl # | Description | Stability | +| ----------------------- | ----------- | ----------- | --------- | +| Proposal | 0 | An idea put forward by a community member to gather feedback | Not stable - breaking changes almost guaranteed as implementers try out the idea. | +| Pilot | 1 | Idea is fleshed out, with examples and a JSON schema, and implemented in one or more catalogs. Additional implementations encouraged to help give feedback | Approaching stability - breaking changes are not anticipated but can easily come from additional feedback | +| Candidate | 3 | A number of implementers are using it and are standing behind it as a solid extension. Can generally count on an extension at this maturity level | Mostly stable, breaking changes require a new version and minor changes are unlikely. The extension has a code owner, designated in its README. | +| Stable | 6 | Highest current level of maturity. The community of extension maintainers commits to a STAC review process for any changes, which are not made lightly. | Completely stable, all changes require a new version number and review process. | +| Deprecated | N/A | A previous extension that has likely been superseded by a newer one or did not work out for some reason. | DO NOT USE, is not supported | + +Maturity mostly comes through diverse implementations, so the minimum number of implementations +column is the main gating function for an extension to mature. But extension authors can also +choose to hold back the maturity advancement if they don't feel they are yet ready to commit to +the less breaking changes of the next level. + +A 'mature' classification level will likely be added once there are extensions that have been +stable for over a year and are used in twenty or more implementations. + +### Prefixes + +A STAC Item can combine schema information from several different sources - the core STAC Item information, +an earth observation community extension, and a vendor specific provider. It can be difficult to distinguish exactly where each definition +came from, and to pull out the most relevant information, especially when vendors often will dump in all the metadata they have in to the +STAC definition. + +So one idea is to have prefixes to differentiate specific vendors (like `dg:` for DigitalGlobe), and for communities of practice +(like `eo:` for Electro-Optical). These wouldn't be full namespacing, though an extension for like JSON-LD could potentially +evolve to make fully resolved namespacing an option. + +An example of this can be seen in a Landsat example: + +```js + "properties": { + "datetime":"2018-01-01T13:21:30Z", + + "start_datetime":"2018-01-01T13:21:30Z", + "end_datetime":"2018-01-01T13:31:30Z", + + "view:off_nadir": -0.001, + "eo:cloud_cover": 10.31, + "view:sun_azimuth": 149.01607154, + "view:sun_elevation": 59.21424700, + "gsd": 30, + + "l8:data_type": "L1T", + "l8:wrs_path": 153, + "l8:wrs_row": 25, + "l8:earth_sun_distance": 1.0141560, + "l8:ground_control_points_verify": 114, + "l8:geometric_rmse_model": 7.562, + "l8:image_quality_tirs": 9, + "l8:ground_control_points_model": 313, + "l8:geometric_rmse_model_x": 5.96, + "l8:geometric_rmse_model_y": 4.654, + "l8:geometric_rmse_verify": 5.364, + "l8:image_quality_oli": 9 + } +``` + +### Use of arrays and objects + +For extensions, it is recommended to + +1. Use arrays only as enumerations/lists (possibly sorted), without implying additional meaning (such as order) +2. To avoid using nested objects, in favor of multiple attributes with a similar naming scheme. + +For example, if one would like to define an extension to contain a start and a end date, there are multiple options (tl;dr: option **3** is recommended): + +1. Define an object, for example: `"date_range": {"start": "2018-01-01", "end": "2018-01-31"}`. This is **discouraged** as it is more complex to search in objects. +2. Define an two-element array where the first element is the start date and the second element is the end date, for example `"date_range": ["2018-01-01", "2018-01-31"]`. This is **discouraged** as it would conflict with Collection `summaries`, which always considers arrays as true (potentially sorted) enumeration without any additional meaning. +3. Define two separate fields, e.g. `"date_range_start": "2018-01-01", "date_range_end": "2018-01-31"`. This is **recommended** as it avoids the conflicts above and is usually better displayed in software that only understands GeoJSON but has no clue about STAC. This is due to the fact that most legacy software can not display arrays or objects GeoJSON `properties` properly. + +This rules only applies to the fields defined directly for the Item's `properties`. For fields and structures defined on other levels (e.g. in the root of an Item or in an array), extension authors can freely define the structure. So an array of objects such as the `eo:bands` are fine to use, but keep in mind that the drawbacks mentioned above usually still apply. diff --git a/item-spec/README.md b/item-spec/README.md new file mode 100644 index 00000000..cd45a670 --- /dev/null +++ b/item-spec/README.md @@ -0,0 +1,23 @@ +# STAC Item Specification + +The [STAC Item](item-spec.md) object is the most important object in a STAC system. An +**Item** is the entity that contains metadata for a scene and links to the assets. + +Item objects are the leaf nodes for a graph of [Catalog](../catalog-spec/catalog-spec.md) +and [Collection](../collection-spec/collection-spec.md) objects. See the +[overview](../overview.md) document for more information about how these objects relate +to each other. + +## In this directory + +**Specification:** The STAC Item specification is in +*[item-spec.md](item-spec.md)*. It includes an overview and an in-depth explanation of the fields. + +**Schemas:** The OpenAPI specification in *[item.json](json-schema/item.json)* +defines an **Item** object. The [basics](json-schema/basics.json), +[datetime](json-schema/datetime.json), [instrument](json-schema/instrument.json), +[licensing](json-schema/licensing.json), and [provider](json-schema/provider.json) +schemas validate additional fields defined in *[Common Metadata](common-metadata.md)*. + +**Common Metadata:** A set of commonly-used fields for STAC Items is listed in +*[common-metadata.md](common-metadata.md)*. diff --git a/item-spec/common-metadata.md b/item-spec/common-metadata.md new file mode 100644 index 00000000..2a0506ca --- /dev/null +++ b/item-spec/common-metadata.md @@ -0,0 +1,186 @@ +# STAC Common Metadata + +This document outlines commonly used fields in STAC. +They are often used in [STAC Item properties](item-spec.md#properties-object), +but can also be used in other places, e.g. an [Item Asset](item-spec.md#asset-object) +or [Collection Asset](../collection-spec/collection-spec.md#asset-object). + +- [STAC Common Metadata](#stac-common-metadata) + - [Basics](#basics) + - [Date and Time](#date-and-time) + - [Date and Time Range](#date-and-time-range) + - [Licensing](#licensing) + - [Relation types](#relation-types) + - [Provider](#provider) + - [Provider Object](#provider-object) + - [Instrument](#instrument) + +Various *examples* are available in the folder [`examples`](../examples/). +*JSON Schemas* can be found in the folder [`json-schema`](json-schema/). + +By default, these fields are only included and validated against in the core [Item schema](json-schema/item.json). +Implementation of any of the fields is not required, +if the specifications allowing these fields to be used don't say differently. +For example, `datetime` is required in STAC Items. + +## Basics + +Descriptive fields to give a basic overview of a STAC Item. + +- [JSON Schema](json-schema/basics.json) + +| Field Name | Type | Description | +| ----------- | ------ | ------------------------------------------------------------ | +| title | string | A human readable title describing the Item. | +| description | string | Detailed multi-line description to fully explain the Item. [CommonMark 0.29](https://commonmark.org/) syntax MAY be used for rich text representation. | + +## Date and Time + +- [JSON Schema](json-schema/datetime.json) + +Fields to provide additional temporal information such as ranges with a start and an end datetime stamp. + +| Field Name | Type | Description | +| ---------- | ------------ | ----------- | +| datetime | string\|null | See the [Item Spec Fields](item-spec.md#properties-object) for more information. | +| created | string | Creation date and time of the corresponding data (see below). | +| updated | string | Date and time the corresponding data (see below) was updated last. | + +All timestamps MUST be formatted according to [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6). + +**created** and **updated** have different meaning depending on where they are used. +If those fields are available in the Item `properties`, it's referencing to the creation and update times of the metadata. +Having those fields in the Item `assets` refers to the creation and update times of the actual data linked to in the Asset Object. + +*NOTE: There are more date and time related fields available in the [Timestamps +extension](https://github.com/stac-extensions/timestamps), which is not an official extension*. + +### Date and Time Range + +While a STAC Item can have a nominal datetime describing the capture, these properties allow an Item to have a range +of capture dates and times. An example of this is the [MODIS 16 day vegetation index product.](https://lpdaac.usgs.gov/products/mod13q1v006/). +The datetime property in a STAC Item and these fields are not mutually exclusive. + +**Important:** Using one of the fields REQUIRES to include the other field as well to enable a user to search STAC records by the provided times. So if you use `start_datetime` you need to add `end_datetime` and vice-versa. Both fields are also REQUIRED if the `datetime` field is set to `null`. + +| Field Name | Type | Description | +| -------------- | ------ | ------------------------------------------------------------ | +| start_datetime | string | The first or start date and time for the Item, in UTC. It is formatted as `date-time` according to [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6). | +| end_datetime | string | The last or end date and time for the Item, in UTC. It is formatted as `date-time` according to [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6). | + +## Licensing + +Information about the license(s) of the data, which is not necessarily the same license that applies to the metadata. +**Licensing information should be defined at the [Collection](../collection-spec/collection-spec.md) level if possible.** + +- [JSON Schema](json-schema/licensing.json) + +| Field Name | Type | Description | +| ---------- | ------ | ----------- | +| license | string | Item's license(s), either a SPDX [License identifier](https://spdx.org/licenses/), `various` if multiple licenses apply or `proprietary` for all other cases. Should be defined at the Collection level if possible. | + +**license**: Data license(s) as a SPDX [License identifier](https://spdx.org/licenses/). Alternatively, use +`proprietary` (see below) if the license is not on the SPDX license list or `various` if multiple licenses apply. +In all cases links to the license texts SHOULD be added, see the [`license` link relation type](#relation-types). +If no link to a license is included and the `license` field is set to `proprietary`, the Collection is private, +and consumers have not been granted any explicit right to use the data. + +### Relation types + +| Type | Description | +| ------------ | ------------------------------------------------------------ | +| license | The license URL(s) for the Item SHOULD be specified if the `license` field is set to `proprietary` or `various`. If there is no public license URL available, it is RECOMMENDED to supplement the STAC Item with the license text in a separate file and link to this file. | + +## Provider + +Information about the organizations capturing, producing, processing, hosting or publishing this data. +**Provider information should be defined at the Collection level if possible.** + +- [JSON Schema](json-schema/provider.json) + +| Field Name | Type | Description | +| ---------- | ------ | ----------- | +| providers | [[Provider Object](#provider-object)] | A list of providers, which may include all organizations capturing or processing the data or the hosting provider. Providers should be listed in chronological order with the most recent provider being the last element of the list. | + +### Provider Object + +The object provides information about a provider. A provider is any of the organizations that captures or processes the content of the assets and therefore influences the data offered by the STAC implementation. May also include information about the final storage provider hosting the data. + +| Field Name | Type | Description | +| ----------- | --------- | ------------------------------------------------------------ | +| name | string | **REQUIRED.** The name of the organization or the individual. | +| description | string | Multi-line description to add further provider information such as processing details for processors and producers, hosting details for hosts or basic contact information. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | +| roles | \[string] | Roles of the provider. Any of `licensor`, `producer`, `processor` or `host`. | +| url | string | Homepage on which the provider describes the dataset and publishes contact information. | + +#### roles + +The provider's role(s) can be one or more of the following elements: + +* *licensor*: The organization that is licensing the dataset under the license specified in the Collection's `license` field. +* *producer*: The producer of the data is the provider that initially captured and processed the source data, e.g. ESA for Sentinel-2 data. +* *processor*: A processor is any provider who processed data to a derived product. +* *host*: The host is the actual provider offering the data on their storage. There should be no more than one host, specified as last element of the list. + +## Instrument + +Adds metadata specifying a platform and instrument used in a data collection mission. These fields will often be combined +with domain-specific extensions that describe the actual data, such as the `eo` or `sar` extensions. + +- [JSON Schema](json-schema/instrument.json) + +| Field Name | Type | Description | +| ------------- | --------- | ----------- | +| platform | string | Unique name of the specific platform to which the instrument is attached. | +| instruments | \[string] | Name of instrument or sensor used (e.g., MODIS, ASTER, OLI, Canon F-1). | +| constellation | string | Name of the constellation to which the platform belongs. | +| mission | string | Name of the mission for which data is collected. | +| gsd | number | Ground Sample Distance at the sensor, in meters (m), must be greater than 0. | + +### Additional Field Information + +#### platform + +The unique name of the specific platform the instrument is attached to. For satellites this would +be the name of the satellite, whereas for drones this would be a unique name for the drone. Examples include +`landsat-8` (Landsat-8), `sentinel-2a` and `sentinel-2b` (Sentinel-2), `terra` and `aqua` (part of NASA EOS, +carrying the MODIS instruments), `mycorp-uav-034` (hypothetical drone name), and `worldview02` +(Maxar/DigitalGlobe WorldView-2). + +#### instruments + +An array of all the sensors used in the creation of the data. For example, data from the Landsat-8 +platform is collected with the OLI sensor as well as the TIRS sensor, but the data is distributed together so would be +specified as `['oli', 'tirs']`. Other instrument examples include `msi` (Sentinel-2), `aster` (Terra), and `modis` +(Terra and Aqua), `c-sar` (Sentinel-1) and `asar` (Envisat). + +#### constellation + +The name of a logical collection of one or more platforms that have similar payloads and have +their orbits arranged in a way to increase the temporal resolution of acquisitions of data with similar geometric and +radiometric characteristics. This field allows users to search for related data sets without the need to specify which +specific platform the data came from, for example, from either of the Sentinel-2 satellites. Examples include `landsat-8` +(Landsat-8, a constellation consisting of a single platform), `sentinel-2` +([Sentinel-2](https://www.esa.int/Our_Activities/Observing_the_Earth/Copernicus/Sentinel-2/Satellite_constellation)), +`rapideye` (operated by Planet Labs), and `modis` (NASA EOS satellites Aqua and Terra). In the case of `modis`, this +is technically referring to a pair of sensors on two different satellites, whose data is combined into a series of +related products. Additionally, the Aqua satellite is technically part of the A-Train constellation and Terra is not +part of a constellation, but these are combined to form the logical collection referred to as MODIS. + +#### mission + +The name of the mission or campaign for collecting data. This could be a discrete set of data collections +over a period of time (such as collecting drone imagery), or could be a set of tasks of related tasks from a satellite +data collection. + +#### gsd + +The nominal Ground Sample Distance for the data, as measured in meters on the ground. There are many +definitions of GSD. The value of this field should be related to the spatial resolution at the sensor, rather +than the pixel size of images after orthorectification, pansharpening, or scaling. +The GSD of a sensor can vary depending on off-nadir and wavelength, so it is at the discretion of the implementer +to decide which value most accurately represents the GSD. For example, Landsat8 optical and short-wave IR bands +are all 30 meters, but the panchromatic band is 15 meters. The +`gsd` should be 30 meters in this case because that is nominal spatial resolution at the sensor. The Planet +PlanetScope Ortho Tile Product has an `gsd` of 3.7 (or 4 if rounding), even though the pixel size of the images is 3.125. For example, one might choose for WorldView-2 the +Multispectral 20° off-nadir value of 2.07 and for WorldView-3 the Multispectral 20° off-nadir value of 1.38. diff --git a/item-spec/item-spec.md b/item-spec/item-spec.md new file mode 100644 index 00000000..84209294 --- /dev/null +++ b/item-spec/item-spec.md @@ -0,0 +1,306 @@ +# STAC Item Specification + +- [Overview](#overview) +- [Item fields](#item-fields) + - [Additional Field Information](#additional-field-information) + - [stac_version](#stac_version) + - [stac_extensions](#stac_extensions) + - [id](#id) + - [assets](#assets) + - [bbox](#bbox) + - [Properties Object](#properties-object) + - [datetime](#datetime) + - [Additional Fields](#additional-fields) + - [Link Object](#link-object) + - [Relation types](#relation-types) + - [derived_from](#derived_from) + - [Collections](#collections) + - [Asset Object](#asset-object) + - [Asset Media Type](#asset-media-type) + - [Asset Roles](#asset-roles) + - [Asset Role Types](#asset-role-types) + - [Additional Fields for Assets](#additional-fields-for-assets) +- [Media Type for STAC Item](#media-type-for-stac-item) +- [Extensions](#extensions) + +## Overview + +This document explains the structure and content of a SpatioTemporal Asset Catalog (STAC) Item. An **Item** is a +[GeoJSON](http://geojson.org/) [Feature](https://tools.ietf.org/html/rfc7946#section-3.2) augmented with +[foreign members](https://tools.ietf.org/html/rfc7946#section-6) relevant to a STAC object. +These include fields that identify the time range and assets of the Item. An Item is the core +object in a STAC Catalog, containing the core metadata that enables any client to search or crawl +online catalogs of spatial 'assets' (e.g., satellite imagery, derived data, DEMs). + +The same Item definition is used in both [STAC Catalogs](../catalog-spec/README.md) and +the [Item-related API endpoints](https://github.com/radiantearth/stac-api-spec/blob/master/api-spec.md#ogc-api---features-endpoints). +Catalogs are simply sets of Items that are linked online, generally served by simple web servers +and used for crawling data. The search endpoint enables dynamic queries, for example selecting all +Items in Hawaii on June 3, 2015, but the results they return are FeatureCollections of Items. + +Items are represented in JSON format and are very flexible. Any JSON object that contains all the +required fields is a valid STAC Item. + +- Examples: + - See the [minimal example](../examples/simple-item.json), as well as a [more fleshed example](../examples/core-item.json) that contains a number of + current best practices. + - Real world [implementations](https://stacindex.org/catalogs) are also available. +- [JSON Schema](json-schema/item.json) + +## Item fields + +This object describes a STAC Item. The fields `id`, `type`, `bbox`, `geometry` and `properties` are +inherited from GeoJSON. + +| Field Name | Type | Description | +| ---------- | -------------------------------------------------------------------------- | ----------- | +| type | string | **REQUIRED.** Type of the GeoJSON Object. MUST be set to `Feature`. | +| stac_version | string | **REQUIRED.** The STAC version the Item implements. | +| stac_extensions | \[string] | A list of extensions the Item implements. | +| id | string | **REQUIRED.** Provider identifier. The ID should be unique within the [Collection](../collection-spec/collection-spec.md) that contains the Item. | +| geometry | [GeoJSON Geometry Object](https://tools.ietf.org/html/rfc7946#section-3.1) \| [null](https://tools.ietf.org/html/rfc7946#section-3.2) | **REQUIRED.** Defines the full footprint of the asset represented by this item, formatted according to [RFC 7946, section 3.1](https://tools.ietf.org/html/rfc7946#section-3.1). The footprint should be the default GeoJSON geometry, though additional geometries can be included. Coordinates are specified in Longitude/Latitude or Longitude/Latitude/Elevation based on [WGS 84](http://www.opengis.net/def/crs/OGC/1.3/CRS84). | +| bbox | \[number] | **REQUIRED if `geometry` is not `null`.** Bounding Box of the asset represented by this Item, formatted according to [RFC 7946, section 5](https://tools.ietf.org/html/rfc7946#section-5). | +| properties | [Properties Object](#properties-object) | **REQUIRED.** A dictionary of additional metadata for the Item. | +| links | \[[Link Object](#link-object)] | **REQUIRED.** List of link objects to resources and related URLs. A link with the `rel` set to `self` is strongly recommended. | +| assets | Map | **REQUIRED.** Dictionary of asset objects that can be downloaded, each with a unique key. | +| collection | string | The `id` of the STAC Collection this Item references to (see [`collection` relation type](#relation-types)). This field is *required* if such a relation type is present. This field provides an easy way for a user to search for any Items that belong in a specified Collection. Must be a non-empty string. | + +### Additional Field Information + +#### stac_version + +In general, STAC versions can be mixed, but please keep the [recommended best practices](../best-practices.md#mixing-stac-versions) in mind. + +#### stac_extensions + +A list of extensions the Item implements. +This list must only contain extensions that extend the Item itself, see the the 'Scope' column in the list of +extensions. The list contains URLs to the JSON Schema files it can be validated against. +If an extension such as the `tiled-assets` extension has influence on multiple parts of the whole catalog +structure, it must be listed in all affected parts (e.g. Catalog, Collection and Item for the `tiled-assets` extension). + +#### id + +It is important that an Item identifier is unique within a Collection, and that the +[Collection identifier](../collection-spec/collection-spec.md#id) in turn is unique globally. Then the two can be combined to +give a globally unique identifier. Items are *[strongly recommended](#collections)* to have Collections, and not having one makes +it more difficult to be used in the wider STAC ecosystem. If an Item does not have a Collection, then the Item identifier should be unique within its root Catalog. + +As most geospatial assets are already uniquely defined by some +identification scheme from the data provider it is recommended to simply use that ID. Data providers are advised to include sufficient information to make their +IDs globally unique, including things like unique satellite IDs. See the [id section of best practices](../best-practices.md#field-and-id-formatting) for +additional recommendations. + +#### assets + +This is a dictionary of [Asset Objects](#asset-object) data associated with the Item that can be +downloaded or streamed, each with a unique key. +In general, the keys don't have any meaning and are considered to be non-descriptive unique identifiers. +Providers may assign any meaning to the keys for their respective use cases, but must not expect that clients understand them. +To communicate the purpose of an asset better use the `roles` field in the [Asset Object](#asset-object). + +Assets should include the main asset, as well as any 'sidecar' files that are related and help a +client make sense of the data. Examples of this include extended metadata (in XML, JSON, etc.), +unusable data masks, satellite ephemeris data, etc. Some assets (like Landsat data) are represented +by multiple files - all should be linked to. It is generally recommended that different processing +levels or formats are not exhaustively listed in an Item, but instead are represented by related +Items that are linked to, but the best practices around this are still emerging. + +#### bbox + +Bounding Box of the asset represented by this Item using either 2D or 3D geometries, formatted according to [RFC 7946, section 5](https://tools.ietf.org/html/rfc7946#section-5). The length of the array must be 2\*n where n is the number of dimensions. The array contains all axes of the southwesterly most extent followed by all axes of the northeasterly most extent specified in Longitude/Latitude or Longitude/Latitude/Elevation based on [WGS 84](http://www.opengis.net/def/crs/OGC/1.3/CRS84). When using 3D geometries, the elevation of the southwesterly most extent is the minimum depth/height in meters and the elevation of the northeasterly most extent is the maximum. This field enables more naive clients to easily index and search geospatially. STAC compliant APIs are required to compute intersection operations with the Item's geometry field, not its bbox. + +### Properties Object + +Additional metadata fields can be added to the GeoJSON Object Properties. The only required field +is `datetime` but it is recommended to add more fields, see [Additional Fields](#additional-fields) +resources below. + +| Field Name | Type | Description | +| ---------- | ------------ | ------------------------------------------------------------ | +| datetime | string\|null | **REQUIRED.** The searchable date and time of the assets, in UTC. It is formatted according to [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6). `null` is allowed, but requires `start_datetime` and `end_datetime` from [common metadata](common-metadata.md#date-and-time-range) to be set. | + +#### datetime + +This is likely the acquisition (in the case of single camera type captures) or the 'nominal' +or representative time in the case of assets that are combined together. Though time can be a +complex thing to capture, for this purpose keep in mind the STAC spec is primarily searching for +data, so use whatever single date and time is most useful for a user to search for. STAC content +extensions may further specify the meaning of the main `datetime` field, and many will also add more +datetime fields. +If there's clearly no meaningful single 'nominal' time, it is allowed to use `null` instead. +In this case it is **required** to specify a temporal interval with the fields `start_datetime` +and `end_datetime` from [common metadata](common-metadata.md#date-and-time-range). For example, if +your data is a time-series that covers 100 years, it's not very meaningful to set the datetime to a +single timestamp as it would not be found in most searches that searches for a decade of data in that +period although the Item actually covers the decade. See [datetime selection](../best-practices.md#datetime-selection) +in the best practices document for more information. + +#### Additional Fields + +Providers should include metadata fields that are relevant for users of STAC, but it is recommended +to [select only those necessary for search](../best-practices.md#field-selection-and-metadata-linking). +Where possible metadata fields should be mapped to the STAC Common Metadata and widely used extensions, +to enable cross-catalog search on known fields. + +* [STAC Common Metadata](common-metadata.md#stac-common-metadata) - A list of fields commonly used +throughout all domains. These optional fields are included for STAC Items by default. +* [Extensions](../extensions/README.md) - Additional fields that are more specific, +such as [EO](https://github.com/stac-extensions/eo), [View](https://github.com/stac-extensions/view). +* [Custom Extensions](../extensions/README.md#extending-stac) - It is generally allowed to add custom +fields but it is recommended to add multiple fields for related values instead of a nested object, +e.g., two fields `view:azimuth` and `view:off_nadir` instead of a field `view` with an object +value containing the two fields. The convention (as used within Extensions) is for related fields +to use a common prefix on the field names to group them, e.g. `view`. A nested data structure should +only be used when the data itself is nested, as with `eo:bands`. + +### Link Object + +This object describes a relationship with another entity. Data providers are advised to be liberal +with the links section, to describe things like the Catalog an Item is in, related Items, parent or +child Items (modeled in different ways, like an 'acquisition' or derived data). +It is allowed to add additional fields such as a `title` and `type`. + +| Field Name | Type | Description | +| ---------- | ------ | ----------- | +| href | string | **REQUIRED.** The actual link in the format of an URL. Relative and absolute links are both allowed. | +| rel | string | **REQUIRED.** Relationship between the current document and the linked document. See chapter "Relation types" for more information. | +| type | string | [Media type](../catalog-spec/catalog-spec.md#media-types) of the referenced entity. | +| title | string | A human readable title to be used in rendered displays of the link. | + +For a full discussion of the situations where relative and absolute links are recommended see the +['Use of links'](../best-practices.md#use-of-links) section of the STAC best practices. + +#### Relation types + +STAC Items use a variety of `rel` types in the link object, to describe the exact nature of the link between this Item and the entity it is linking to. +It is recommended to use the official [IANA Link Relation Types](https://www.iana.org/assignments/link-relations/link-relations.xhtml) where possible. +The following table explains places where STAC use custom `rel` types are used with Items. +This happens where there is not a clear official option, or where STAC uses an official type but adds additional meaning for the STAC context. + +| Type | Description | +| ------------ | ------------------------------------------------------------ | +| self | STRONGLY RECOMMENDED. *Absolute* URL to the Item if it is available at a public URL. This is particularly useful when in a download package that includes metadata, so that the downstream user can know where the data has come from. | +| root | URL to the root STAC Catalog or Collection. | +| parent | URL to the parent STAC Catalog or Collection. | +| collection | STRONGLY RECOMMENDED. URL to a Collection. *Absolute* URLs should be used whenever possible. The referenced Collection is STRONGLY RECOMMENDED to implement the same STAC version as the Item. | +| derived_from | URL to a STAC Item that was used as input data in the creation of this Item. | + +A more complete list of potential `rel` types and their meaning in STAC can be found in the [Using Relation +Types](../best-practices.md#using-relation-types) best practice. + +##### derived_from + +*Note regarding the type `derived_from`: A full provenance model is far beyond the scope of STAC, and the goal is to align with any good independent spec +that comes along for that. But the derived_from field is seen as a way to encourage fuller specs and at least start a linking +structure that can be used as a jumping off point for more experiments in provenance tracking* + +#### Collections + +Items are *strongly recommended* to provide a link to a STAC Collection definition. It is important as Collections provide additional information about a set of items, for example the license, provider and other information +giving context on the overall set of data that an individual Item is a part of. + +If Items are part of a STAC Collection, the [STAC Collection spec *requires* Items to link back to the Collection](../collection-spec/collection-spec.md#relation-types). +Linking back must happen in two places: + +1. The field `collection` in an Item must be filled (see section 'Item fields'). It is the `id` of a STAC Collection. +2. An Item must also provide a link to the STAC Collection using the [`collection` relation type](#relation-types): + ```js + "links": [ + { "rel": "collection", "href": "link/to/collection/record.json" } + ] + ``` + +### Asset Object + +An Asset is an object that contains a URI to data associated with the Item that can be downloaded +or streamed. It is allowed to add additional fields. + +| Field Name | Type | Description | +| ----------- | --------- | ----------- | +| href | string | **REQUIRED.** URI to the asset object. Relative and absolute URI are both allowed. | +| title | string | The displayed title for clients and users. | +| description | string | A description of the Asset providing additional details, such as how it was processed or created. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | +| type | string | [Media type](#asset-media-type) of the asset. See the [common media types](../best-practices.md#common-media-types-in-stac) in the best practice doc for commonly used asset types. | +| roles | \[string] | The [semantic roles](#asset-roles) of the asset, similar to the use of `rel` in links. | + +[Additional fields](#additional-fields) *may* be added to the assets, though this +is recommended only in special cases. See [Additional Fields for Assets](#additional-fields-for-assets)) for more information. + +#### Asset Media Type + +Any media type can be used in an Item's asset `type` field, and [registered](https://www.iana.org/assignments/media-types/media-types.xhtml) +Media Types are preferred. STAC Items that have sidecar metadata files associated with a data asset (e.g, `.tfw`, Landsat 8 MTL files) +should use media types appropriate for the the metadata file. For example, if it is a plain text file, then `text/plain` +would be appropriate; if it is an XML, then `text/xml` is appropriate. For more information on media types as well as a +list of [common media types](../best-practices.md#common-media-types-in-stac) used in STAC see the [best practice on +working with media types](../best-practices.md#working-with-media-types). + +#### Asset Roles + +The `roles` field is used to describe the purpose of each asset. It is recommended to include one for every asset, to give users +a sense of why they might want to make use of the asset. There are some emerging standards that enable clients to take particular +action when they encounter particular roles, listed below. But implementors are encouraged to come up with their own terms to +describe the role. + +##### Asset Role Types + +Like the Link `rel` field, the `roles` field can be given any value, however here are a few standardized role names. + +| Role Name | Description | +| --------- | ------------------------------------------------------------------------------------- | +| thumbnail | An asset that represents a thumbnail of the Item, typically a true color image (for Items with assets in the visible wavelengths), lower-resolution (typically smaller 600x600 pixels), and typically a JPEG or PNG (suitable for display in a web browser). Multiple assets may have this purpose, but it recommended that the `type` and `roles` be unique tuples. For example, Sentinel-2 L2A provides thumbnail images in both JPEG and JPEG2000 formats, and would be distinguished by their media types. | +| overview | An asset that represents a possibly larger view than the thumbnail of the Item, for example, a true color composite of multi-band data. | +| data | The data itself. This is a suggestion for a common role for data files to be used in case data providers don't come up with their own names and semantics. | +| metadata | A metadata sidecar file describing the data in this Item, for example the Landsat-8 MTL file. | + +It is STRONGLY RECOMMENDED to add to each STAC Item +* a thumbnail with the role `thumbnail` for preview purposes +* one or more data file although it doesn't need to use the suggested role `data` + +Note that multiple roles per asset are encouraged: pick all the ones that apply. So many should have the 'data' role, and then +another role to describe how the data is used. For more information on how to use roles see the [Asset +Roles](../best-practices.md#asset-roles) section of the Best Practices document. It includes a [list of asset +roles](../best-practices.md#list-of-asset-roles) that include many more ideas on roles to use. As they reach more widespread +adoption we will include them here. + +#### Additional Fields for Assets + +As detailed above, Items contain properties, which are the main source of metadata for searching across Items. Many content +extensions can add further property fields as well. Any property that can be specified for an Item can also be specified for +a specific asset. This can be used to override a property defined in the Item, or to specify fields for which there is no +single value for all assets. + +**It is important to note that the STAC API does not facilitate searching across Asset properties in this way, and this +should be used sparingly.** It is primarily used to define properties at the Asset level that may be used during use of +the data instead of for searching. + +For example, `gsd` defined for an Item represents the best Ground Sample Distance (resolution) for the data within the Item. +However, some assets may be lower resolution and thus have a higher `gsd`. The `eo:bands` field from the EO extension defines +an array of spectral bands. However, it may be useful instead to specify the bands that are used in a particular asset. + +For an example see the [sentinel2-sample](https://github.com/stac-utils/stac-examples/blob/main/sentinel2/sentinel2-sample.json). The Sentinel-2 overall `gsd` is 10m, because this is +the best spatial resolution among all the bands and is defined in Item properties so it can be searched on. In the example +Band 5 and others have a `gsd` of 20m, so that asset specifies the `gsd` as well, which overrides the Item `gsd` for this +one asset. The example also includes reduced resolution versions of files included as assets, using `gsd` to represent +the proper resolution. + +For `eo:bands`, it could be put in Item properties as an array of all the bands, but in this case it's not. Instead, +the assets each define an array containing the spectral band information for that asset (in the order the bands appear +in the file). + +For examples of fields that this construct is recommended for, see the [section of STAC Best Practices](../best-practices.md#common-use-cases-of-additional-fields-for-assets) +that talks about common use cases of additional fields for assets. + +## Media Type for STAC Item + +A STAC Item is a GeoJSON file ([RFC 7946](https://tools.ietf.org/html/rfc7946)), and thus should use the +[`application/geo+json`](https://tools.ietf.org/html/rfc7946#section-12) as the [Media Type](https://en.wikipedia.org/wiki/Media_type) +(previously known as the MIME Type). + +## Extensions + +There are emerging best practices, which in time will evolve in to specification extensions for +particular domains or uses. + +The [extensions page](../extensions/README.md) gives an overview about relevant extensions for STAC Items. diff --git a/item-spec/json-schema/basics.json b/item-spec/json-schema/basics.json new file mode 100644 index 00000000..a5b26a3d --- /dev/null +++ b/item-spec/json-schema/basics.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/item-spec/json-schema/basics.json#", + "title": "Basic Descriptive Fields", + "type": "object", + "properties": { + "title": { + "title": "Item Title", + "description": "A human-readable title describing the Item.", + "type": "string" + }, + "description": { + "title": "Item Description", + "description": "Detailed multi-line description to fully explain the Item.", + "type": "string" + } + } +} \ No newline at end of file diff --git a/item-spec/json-schema/datetime.json b/item-spec/json-schema/datetime.json new file mode 100644 index 00000000..3a1480db --- /dev/null +++ b/item-spec/json-schema/datetime.json @@ -0,0 +1,48 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/item-spec/json-schema/datetime.json#", + "title": "Date and Time Fields", + "type": "object", + "dependencies": { + "start_datetime": { + "required": [ + "end_datetime" + ] + }, + "end_datetime": { + "required": [ + "start_datetime" + ] + } + }, + "properties": { + "datetime": { + "title": "Date and Time", + "description": "The searchable date/time of the assets, in UTC (Formatted in RFC 3339) ", + "type": ["string", "null"], + "format": "date-time" + }, + "start_datetime": { + "title": "Start Date and Time", + "description": "The searchable start date/time of the assets, in UTC (Formatted in RFC 3339) ", + "type": "string", + "format": "date-time" + }, + "end_datetime": { + "title": "End Date and Time", + "description": "The searchable end date/time of the assets, in UTC (Formatted in RFC 3339) ", + "type": "string", + "format": "date-time" + }, + "created": { + "title": "Creation Time", + "type": "string", + "format": "date-time" + }, + "updated": { + "title": "Last Update Time", + "type": "string", + "format": "date-time" + } + } +} \ No newline at end of file diff --git a/item-spec/json-schema/instrument.json b/item-spec/json-schema/instrument.json new file mode 100644 index 00000000..78d836ba --- /dev/null +++ b/item-spec/json-schema/instrument.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/item-spec/json-schema/instrument.json#", + "title": "Instrument Fields", + "type": "object", + "properties": { + "platform": { + "title": "Platform", + "type": "string" + }, + "instruments": { + "title": "Instruments", + "type": "array", + "items": { + "type": "string" + } + }, + "constellation": { + "title": "Constellation", + "type": "string" + }, + "mission": { + "title": "Mission", + "type": "string" + }, + "gsd": { + "title": "Ground Sample Distance", + "type": "number", + "exclusiveMinimum": 0 + } + } +} \ No newline at end of file diff --git a/item-spec/json-schema/item.json b/item-spec/json-schema/item.json new file mode 100644 index 00000000..34d351f3 --- /dev/null +++ b/item-spec/json-schema/item.json @@ -0,0 +1,250 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/item-spec/json-schema/item.json#", + "title": "STAC Item", + "type": "object", + "description": "This object represents the metadata for an item in a SpatioTemporal Asset Catalog.", + "allOf": [ + { + "$ref": "#/definitions/core" + } + ], + "definitions": { + "common_metadata": { + "allOf": [ + { + "$ref": "basics.json" + }, + { + "$ref": "datetime.json" + }, + { + "$ref": "instrument.json" + }, + { + "$ref": "licensing.json" + }, + { + "$ref": "provider.json" + } + ] + }, + "core": { + "allOf": [ + { + "$ref": "https://geojson.org/schema/Feature.json" + }, + { + "oneOf": [ + { + "type": "object", + "required": [ + "geometry", + "bbox" + ], + "properties": { + "geometry": { + "$ref": "https://geojson.org/schema/Geometry.json" + }, + "bbox": { + "type": "array", + "oneOf": [ + { + "minItems": 4, + "maxItems": 4 + }, + { + "minItems": 6, + "maxItems": 6 + } + ], + "items": { + "type": "number" + } + } + } + }, + { + "type": "object", + "required": [ + "geometry" + ], + "properties": { + "geometry": { + "type": "null" + }, + "bbox": { + "not": {} + } + } + } + ] + }, + { + "type": "object", + "required": [ + "stac_version", + "id", + "links", + "assets", + "properties" + ], + "properties": { + "stac_version": { + "title": "STAC version", + "type": "string", + "const": "1.0.0-rc.2" + }, + "stac_extensions": { + "title": "STAC extensions", + "type": "array", + "uniqueItems": true, + "items": { + "anyOf": [ + { + "title": "Reference to a JSON Schema", + "type": "string", + "format": "iri" + }, + { + "title": "Reference to a core extension", + "type": "string" + } + ] + } + }, + "id": { + "title": "Provider ID", + "description": "Provider item ID", + "type": "string", + "minLength": 1 + }, + "links": { + "title": "Item links", + "description": "Links to item relations", + "type": "array", + "items": { + "$ref": "#/definitions/link" + } + }, + "assets": { + "$ref": "#/definitions/assets" + }, + "properties": { + "allOf": [ + { + "$ref": "#/definitions/common_metadata" + }, + { + "anyOf": [ + { + "required": [ + "datetime" + ], + "properties": { + "datetime": { + "not": { + "type": "null" + } + } + } + }, + { + "required": [ + "datetime", + "start_datetime", + "end_datetime" + ] + } + ] + } + ] + }, + "collection": { + "title": "Collection ID", + "description": "The ID of the STAC Collection this Item references to.", + "type": "string", + "minLength": 1 + } + } + } + ] + }, + "link": { + "type": "object", + "required": [ + "rel", + "href" + ], + "properties": { + "href": { + "title": "Link reference", + "type": "string", + "format": "iri-reference", + "minLength": 1 + }, + "rel": { + "title": "Link relation type", + "type": "string", + "minLength": 1 + }, + "type": { + "title": "Link type", + "type": "string" + }, + "title": { + "title": "Link title", + "type": "string" + } + } + }, + "assets": { + "title": "Asset links", + "description": "Links to assets", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/asset" + } + }, + "asset": { + "allOf": [ + { + "type": "object", + "required": [ + "href" + ], + "properties": { + "href": { + "title": "Asset reference", + "type": "string", + "format": "iri-reference", + "minLength": 1 + }, + "title": { + "title": "Asset title", + "type": "string" + }, + "description": { + "title": "Asset description", + "type": "string" + }, + "type": { + "title": "Asset type", + "type": "string" + }, + "roles": { + "title": "Asset roles", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + { + "$ref": "#/definitions/common_metadata" + } + ] + } + } +} diff --git a/item-spec/json-schema/licensing.json b/item-spec/json-schema/licensing.json new file mode 100644 index 00000000..a20dde60 --- /dev/null +++ b/item-spec/json-schema/licensing.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/item-spec/json-schema/licensing.json#", + "title": "Licensing Fields", + "type": "object", + "properties": { + "license": { + "type": "string", + "pattern": "^[\\w\\-\\.\\+]+$" + } + } +} \ No newline at end of file diff --git a/item-spec/json-schema/provider.json b/item-spec/json-schema/provider.json new file mode 100644 index 00000000..b80c734e --- /dev/null +++ b/item-spec/json-schema/provider.json @@ -0,0 +1,47 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0-rc.2/item-spec/json-schema/provider.json#", + "title": "Provider Fields", + "type": "object", + "properties": { + "providers": { + "title": "Providers", + "type": "array", + "items": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "title": "Organization name", + "type": "string", + "minLength": 1 + }, + "description": { + "title": "Organization description", + "type": "string" + }, + "roles": { + "title": "Organization roles", + "type": "array", + "items": { + "type": "string", + "enum": [ + "producer", + "licensor", + "processor", + "host" + ] + } + }, + "url": { + "title": "Organization homepage", + "type": "string", + "format": "iri" + } + } + } + } + } +} \ No newline at end of file diff --git a/overview.md b/overview.md new file mode 100644 index 00000000..3d752aae --- /dev/null +++ b/overview.md @@ -0,0 +1,186 @@ +# STAC Overview + +There are three component specifications that together make up the core SpatioTemporal Asset Catalog specification. +Each can be used alone, but they work best in concert with one another. The [STAC API specification](https://github.com/radiantearth/stac-api-spec) +builds on top of that core, but is out of scope for this overview. An [Item](item-spec/item-spec.md) represents a +single [spatiotemporal asset](#what-is-a-spatiotemporal-asset) as GeoJSON so it can be searched. +The [Catalog](catalog-spec/catalog-spec.md) specification provides structural elements, to group Items +and [Collections](collection-spec/collection-spec.md). Collections *are* catalogs, that add more required metadata and +describe a group of related Items. For more on the differences see the [section below](#catalogs-vs-collections). + +A [UML diagram](https://en.wikipedia.org/wiki/Unified_Modeling_Language) of the [STAC model](STAC-UML.pdf) is also +provided to help with navigating the specification. + +## Item Overview + +Fundamental to any SpatioTemporal Asset Catalog, an [Item](item-spec/item-spec.md) object represents a unit of +data and metadata, typically representing a single scene of data at one place and time. A STAC Item is a +[GeoJSON](http://geojson.org/) [Feature](https://tools.ietf.org/html/rfc7946#section-3.2) +and can be easily read by any modern GIS or geospatial library, and it describes a +[SpatioTemporal Asset](#what-is-a-spatiotemporal-asset). +The STAC Item JSON specification uses the GeoJSON geometry to describe the location of the asset, and +then includes additional information: + +* the time the asset represents; +* a thumbnail for quick browsing; +* asset links, to enable direct download or streaming access of the asset; +* relationship links, allowing users to traverse other related resources and STAC Items. + +A STAC Item can contain additional fields and JSON structures to communicate more information about the +asset, so it can be easily searched. STAC provides a core set of +[Common Metadata](item-spec/common-metadata.md) +and there is a wider community working on a variety of [STAC Extensions](extensions/) that provide shared metadata for +more specific domains. Both aim to describe data with well known, well +defined terms to enable consistent publishing and better search. For more recommendations on selecting fields +for an Item see [this section](best-practices.md#field-selection-and-metadata-linking) of the best practices document. + +### What is a SpatioTemporal Asset + +A 'spatiotemporal asset' is any file that represents information about the earth captured in a certain +space and time. Examples include Imagery (from satellites, planes and drones), SAR, Point Clouds (from +LiDAR, Structure from Motion, etc), Data Cubes, Full Motion Video, and data derived from any of those. +The key is that the GeoJSON is not the actual 'thing', but instead references files and serves as an +index to the 'assets'. It is [not recommended](best-practices.md#representing-vector-layers-in-stac) +to use STAC to refer to traditional vector data layers (shapefile, geopackage) as assets, as they +don't quite fit conceptually. + +## Catalogs vs Collections + +Before we go deep into the Catalogs and Collections, it is worth explaining the relationship +between the two and when you might want to use one or the other. + +A Catalog is a very simple construct - it just provides links to Items or to other Catalogs. +The closest analog is a folder in a file structure, it is the container for Items, but it can +also hold other containers (folders / catalogs). + +The Collection specification shares some fields with the catalog spec but has a number of additional fields: +license, extent (spatial and temporal), providers, keywords and summaries. Every Item in a Collection links +back to their Collection, so clients can easily find fields like the license. Thus every Item implicitly +shares the fields described in their parent Collection. + +But what *should* go in a Collection, versus just in a Catalog? A Collection will generally consist of +a set of assets that are defined with the same properties and share higher level metadata. In the +satellite world these would typically all come from the same sensor or constellation. It corresponds +directly to what others call a "dataset series" (ESA, ISO 19115), "collection" (CNES, NASA), and +"dataset" (JAXA, DCAT). So if all your Items have the same properties, they probably belong in +the same Collection. But the construct is deliberately flexible, as there may be good reasons +to break the recommendation. + +Catalogs in turn are used for two main things: + +* Split overly large collections into groups +* Group collections into a catalog of Collections (e.g. as entry point for navigation to several Collections). + +The first case allows users to browse down into the Items of large collections. A collection like +Landsat usually would start with path and row Catalogs to group by geography, and then year, +month and day groups to enable deeper grouping. [Dynamic catalogs](best-practices.md#dynamic-catalogs) can +provide multiple grouping paths, serving as a sort of faceted search. + +The second case is used when one wants to represent diverse data in a single place. If an organization +has an internal catalog with Landsat 8, Sentinel 2, NAIP data and several commercial imagery providers +then they'd have a root catalog that would link to a number of different Collections. + +So in conclusion it's best to use Collections for what you want user to find as starting point, and then +catalogs are just for structuring and grouping the data. Future work includes a mechanism to actually +search Collection-level data, hopefully in concert with other specifications. + +## Catalog Overview + +There are two required element types of a Catalog: Catalog and Item. A STAC Catalog +points to [STAC Items](item-spec/README.md), or to other STAC catalogs. It provides a simple +linking structure that can be used recursively so that many Items can be included in +a single Catalog, organized however the implementor desires. + +STAC makes no formal distinction between a "root" catalog and the "child" catalogs. A root catalog +is simply the top-most catalog -- it has no parent. A nested catalog structure is useful (and +recommended) for breaking up massive numbers of catalog Items into logical groupings. For example, +it might make sense to organize a catalog by date (year, month, day), or geography (continent, +country, state/prov). See the [Catalog Layout](best-practices.md#catalog-layout) best practices +section for more. + +A simple Catalog structure might look like this: + +- catalog (root) + - catalog + - catalog + - item + - asset + - item + - asset + - item + - asset + - asset + +This example might be considered a somewhat "typical" structure. However, Catalogs and Items can +describe a number of different relationships. The following shows various relationships between +catalogs and items: + +- `Catalog` -> `Item` (this is a common structure for a catalog to list links to Items) +- `Catalog` -> `Catalog` (this is a common tree structure to group sets of Items. Each catalog in + this relationship may also include Item links as well as catalog links) + +The relationships are all described by a common `links` object structure, making use of +the `rel` field to further describe the relationship. + +There are a few types of catalogs that implementors occasionally refer to. These get defined by the `links` structure. + +- A **sub-catalog** is a Catalog that is linked to from another Catalog that is used to better organize data. For example a Landsat collection + might have sub-catalogs for each Path and Row, so as to create a nice tree structure for users to follow. +- A **root catalog** is a Catalog that only links to sub-catalogs. These are typically entry points for browsing data. Often + they will contain the [STAC Collection](collection-spec/) definition, but in implementations that publish diverse information it may + contain sub-catalogs that provide a variety of Collections. +- A **parent catalog** is the Catalog that sits directly above a sub-catalog. Following parent catalog links continuously + will naturally end up at a root catalog definition. + +It should be noted that a Catalog does not have to link back to all the other Catalogs that point to it. Thus a published +root catalog might be a sub-catalog of someone else's structure. The goal is for data providers to publish all the +information and links they want to, while also encouraging a natural web of information to arise as Catalogs and Items are +linked to across the web. + +### Static and Dynamic Catalogs + +The Catalog specification is designed so it can be implemented as easily as possibly. This can be as simple as +simply putting linked json files on a file server or an object storage service (like [AWS S3](https://aws.amazon.com/s3/)), +or it can be generated on the fly by a live server. The first type of implementation is often called a 'static catalog', +and any catalog that is not just files is called a 'dynamic catalog'. You can read more about the two types along with +recommendations in [this section](best-practices.md#static-and-dynamic-catalogs) of the best practices document, +along with how to keep a [dynamic catalog in sync](best-practices.md#static-to-dynamic-best-practices) with a static one. + +### Catalog Best Practices + +In addition to information about different catalog types, the [best practices document](best-practices.md) has +a number of suggestions on how to organize and implement good catalogs. The [catalog specification](catalog-spec/catalog-spec.md) +is designed for maximum flexbility, so none of these are required, but they provide guidance for implementors who +want to follow what most of the STAC community is doing. + +- [Catalog Layout](best-practices.md#catalog-layout) is likely the most important section, as following its +recommendations will enable catalogs to work better with client tooling that optimizes for known layouts. +- [Use of Links](best-practices.md#use-of-links) articulates practices for making catalogs that are portable (with +relative links through out) and ones that are published in stable locations (with absolute self links). +- [Versioning for Catalogs](best-practices.md#versioning-for-catalogs) explains how to use STAC's structure to +keep a history of changes made to Items and catalogs. +- [STAC on the Web](best-practices.md#stac-on-the-web) explains how catalogs should have html versions for +each Item and Catalog, as well as ways to achieve that. + +## Collection Overview + +A STAC Collection extends the core fields of the Catalog construct to provide additional metadata to describe the set of Items it +contains. The required fields are fairly +minimal - it includes the 4 required Catalog fields (id, description, stac_version and links), and adds license +and extents. But there are a number of other common fields defined in the spec, and more common fields are also +defined in [STAC extensions](extensions/). These serve as basic metadata, and ideally Collections also link to +fuller metadata (ISO 19115, etc) when it is available. + +As Collections contain all of Catalogs' core fields, they can be used just as flexibly. They can have both parent Catalogs and Collections +as well as child Items, Catalogs and Collections. Items are strongly recommended to have a link to the Collection +they are a part of. Items can only belong to one Collection, so if an Item is in a Collection that is the child of +another Collection, then it must pick which one to refer to. Generally the 'closer' Collection, the more specific +one, should be the one linked to. + +The Collection specification is used standalone quite easily - it is used to describe an aggregation of data, +and doesn't require links down to sub-catalogs and Items. This is most often used when the software +does operations at the layer / coverage level, letting users manipulate a whole collection of assets at once. They often +have an optimized internal format that doesn't make sense to expose as Items. [OpenEO](https://openeo.org/) and +[Google Earth Engine](https://earthengine.google.com/) are two examples that only use STAC collections, and +both would be hardpressed to expose individual Items due to their architectures. For others implementing STAC +Collections can also be a nice way to start and achieve some level of interoperability. diff --git a/package.json b/package.json new file mode 100644 index 00000000..3fb2aeee --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "stac-spec", + "version": "1.0.0-rc.2", + "description": "STAC spec helpers to check the spec.", + "repository": "https://github.com/radiantearth/stac-spec", + "license": "Apache-2.0", + "scripts": { + "check": "npm run check-markdown && npm run check-examples", + "check-markdown": "remark . -f -r .circleci/rc.yaml", + "check-examples": "stac-node-validator . --lint --verbose --schemas .", + "format-examples": "stac-node-validator . --format --schemas .", + "publish-schemas": "node .circleci/publish-schemas.js" + }, + "dependencies": { + "gh-pages": "^3.0.0", + "klaw-sync": "^6.0.0", + "remark-cli": "^8.0.0", + "remark-lint": "^7.0.0", + "remark-lint-no-html": "^2.0.0", + "remark-preset-lint-consistent": "^3.0.0", + "remark-preset-lint-markdown-style-guide": "^3.0.0", + "remark-preset-lint-recommended": "^4.0.0", + "remark-validate-links": "^10.0.0", + "stac-node-validator": "^0.4.6" + } +} diff --git a/principles.md b/principles.md new file mode 100644 index 00000000..03306596 --- /dev/null +++ b/principles.md @@ -0,0 +1,45 @@ +This project will be governed by a set of informal core principles. These principles are not set in stone, +and indeed they should evolve in the same manner that all specifications worked on should - proposed and +reviewed in pull requests, approved by consensus. The goal of the principles is to help avoid +[bikeshedding](http://bikeshed.org/) - lay down some meta-rules so we can focus on creating useful +core geospatial standards. + +* **Creation and evolution of specs in Github**, using Open Source principles +(please read [Producing OSS](http://producingoss.com/) if that phrase doesn't immediately make sense to you). +The collaboration facilities of Github should be used to their full extent. All proposed improvements and +changes should come in the form of pull requests, using code review functionality to discuss changes. + +* **JSON + REST + HTTP at the core.** JSON has won over XML, and REST over SOAP. We embrace them and +are not considering legacy options. Forward looking protocols can be considered as extensions, +but the default specifications should be in JSON, following best REST practices. HTTP caching and +error codes should be leveraged at the core. GeoJSON has already defined the core geospatial JSON response, +so it should also be core. [JSON API](http://jsonapi.org/) should be used as basis of decisions where possible. + +* **Small Reusable Pieces Loosely Coupled** - Each specification should be as focused as possible, +defining one core concept and refraining from describing lots of options. Additional options can be made +as separate specifications that build on the core. But the core specs should be small and easily understandble, +with clear defaults for any choice. Handling complex cases should be possible by combining discrete pieces. +Implementors should not be forced to implement lots of options just for basic compliance - they should be +able to pick and choose which pieces are relevant to the problems they are trying to solve. + +* **Focus on the developer**. Specifications should aim for implementability - any explanation or design choice +should be considered with a developer audience. And specifications should be accessible to developers who do not +have geospatial background. A developer should not need to understand 'projections' to implement a simple feature +access service. But we should think through the spec extensions they could use in the future when their client asks +for data in a different projection. + +* **Working code required.** Proposed changes should be accompanied by working code +(ideally with a link to an online service running the code). A reference implementation should be available +online to power the interactive documentation. Fully accepted specifications should have at least 3 implementations +that cover the entire specification. Extensions have their own [Extension Maturity](./extensions/README.md#extension-maturity) model. + +* **Design for scale.** The design should work great with more data than can be imagined right now. +Ideally implementations are built with large test data sets to validate that they will work. +Everything should be compatible with content distribution network (CDN) caching. + +## Resources + +* Open Source Principles - [Producing Open Source Software](http://producingoss.org) by Karl Fogel. +* Best Practices JSON API Design - [JSON API](http://jsonapi.org/) best practices for making API's with JSON +* Pragmatic REST - [Web API Design: Crafting interfaces that developers love](https://pages.apigee.com/rs/apigee/images/api-design-ebook-2012-03.pdf) +* Open API Initiative - [OpenAPIs.org](https://openapis.org/) diff --git a/process.md b/process.md new file mode 100644 index 00000000..2250e844 --- /dev/null +++ b/process.md @@ -0,0 +1,119 @@ +## STAC Development & Release Process + +### Development Process + +The SpatioTemporal Asset Catalog specification is under active development. The goal is to get to a small, flexible stable +release that can be extended in a variety of ways. The core development team aims to release early and often, which generally +has meant a new release between two and four months since the previous one. + +The `master` branch aims to always be stable, meaning that all the pieces of the specification are consistent and well +explained, and all the examples are consistent with the specification. The `dev` branch is a place of active development, +where a new change in one part of the spec might not yet be fully updated everywhere else. The team uses the +[stac-spec issue tracker](https://github.com/radiantearth/stac-spec/issues) to identify and track all that will be done for +a release. Once all the major issues are resolved the core team makes sure everything is consistent across the spec and +examples. + +Any changes to the spec must be made as pull requests to the `dev` branch. Anyone is welcome and encouraged to bring ideas +and improvements, to the issue tracker or (ideally) as pull requests. To merge a new pull request the work must be reviewed +by at least two members of the STAC spec 'core team' (who have write access to the main repository). It also must pass the +Continuous Integration (CI) testing, which checks all markdown and example files for proper formatting, and also validates all +examples against JSON schema. For more information about making pull requests see [CONTRIBUTING.md](CONTRIBUTING.md), +and there is also information on how to [run the CI checks locally](CONTRIBUTING.md#check-files). + +#### Core STAC Team + +The current list of people who are part of the 'core STAC team', and can approve pull requests. + +* [Alex Kaminsky](https://github.com/alkamin) +* [Alexandra Kirk](https://github.com/anayeaye) +* [Chris Holmes](http://github.com/cholmes) +* [Emmanuel Mathot](https://github.com/emmanuelmathot) +* [Michael Smith](https://github.com/hgs-msmith) +* [James Banting](https://github.com/jbants) +* [James Santucci](https://github.com/jisantuc) +* [Josh Fix](https://github.com/joshfix) +* [Rob Emanuele](https://github.com/lossyrob) +* [Matthias Mohr](https://github.com/m-mohr) +* [Matt Hanson](https://github.com/matthewhanson) +* [Phil Varner](https://github.com/philvarner) + +Anyone can be nominated to the core STAC team, and that generally happens after contributing a few pull requests +and/or helping review other PR's. Nominations are reviewed by the [PSC](#project-steering-committee), and must recieve +3 positive votes and no negatives. + +### Release Process + +To release a new version of the STAC spec the following list of tasks must be done. + +* **Update Issue Tracker**: Each release has a [milestone](https://github.com/radiantearth/stac-spec/milestones) in the github +issue tracker, and before a release is done all open issues that are filed against it should be reviewed. All issues do not +need to be completed, but the core release team should all review the issues to make sure that the critical ones for the +release have been addressed. Issues that aren't seen as essential should be moved to future releases, so that there are no +open issues against the milestone. +* **Agreement from the Project Steering Committee**: The PSC should meet (on phone or on gitter) and decided that the release is ready. +This should include review of the issues, as well as looking at the spec holistically, to make sure the new changes keep +with a coherent whole. +* **Final Spec Read Through**: There should be a final read through of the core specification to make sure it makes sense +and there are no typos, errors, etc. +* **Update the version numbers**: There are several places in the spec that use the version number or a branch name in text +or a link. These include the markdown files and the JSON schemas. Right now the best thing to do is just a search & replace +for the last version number and `https://schemas.stacspec.org/dev/` with `https://schemas.stacspec.org//` +(in JSON Schemas, don't replace it here). `` must correspond with the tag on GitHub, usually including a leading `v`. +Hopefully in the future there will be scripts to do this. +* **Update the Changelog**: The [changelog](CHANGELOG.md) should be reviewed to make sure it includes all major improvements +in the release. And anything in 'unreleased' section should move to the version of the spec to be released. +* **Merge dev to master**: As there is no 'build' process, since the specification *is* the markdown files in the github +repository, the key step in a release is to merge the `dev` branch into `master`, as `master` is the current stable state +of the spec. +* **Release on Github**: The final step to create the release is to add a new 'release' on +. This should use a tag like the others, with a 'v' prefix and then the +release number, like v0.5.2. The changelog should be copied over to be the release notes, and then also include a link to +the full milestone of everything closed in the issue tracker. +* **Promote the release**: A blog post and tweet should be composed and sent out, and then inform those in the gitter channel +to post / promote it. + +#### Release Candidates + +Before any release that has *major* changes (made as a judgement call by the core contributors) there should be a 'release +candidate' to ensure the wider community of implementors can try it out +and catch any errors *before* a full release. It is only through actual implementations that we can be sure the new spec +version is good, so this step is essential if there are major changes. The release should proceed as normal, but called +vX.Y.Z-rc.1. The core STAC community should be told and encouraged to update their implementations. At least 2 implementations +should be updated to the new specification before there is a real release. And ideally a client like STAC Browser is also +updated. This provides the core sanity check. If there are changes or fixes to the spec or +schemas needed from their feedback then make fixes and do rc.2. If it is just fixes to the examples or tooling then no +additional RC is needed. After there is no more changes to spec or schemas then the release process should be done on master, +with no changes to the spec - just updating the version numbers. + +### Governance + +The vast majority of decisions on STAC are made by the [Core STAC Team](#core-stac-team) reaching consensus in +discussions in pull requests and issues. Any change to the specification must have two positive reviews and no negative +reviews. + +#### Project Steering Committee + +For the rare case where a decision cannot be reached by consensus, there is a Project Steerting Committee that has ultimate +decision making authority. This consists of individuals who are intended to represent the various communities which have a +stake in the specification and surrounding ecosystem. An odd number is chosen to facilitate the voting process and help prevent ties. +This committee also handles the allocation of any funds that are raised for the project. + +Turnover is allowed and expected to accommodate people only able to become active on the project in intervals. A PSC member may step down at any time. + +#### Current Project Steering Committee + +* [Matthias Mohr](https://github.com/m-mohr) - University of Muenster, [OpenEO](https://openeo.org/) and [Radiant Earth](https://www.radiant.earth/) +* [Matt Hanson](https://github.com/matthewhanson) - [Element 84](https://www.element84.com/) +* [James Banting](https://github.com/jbants) - [SparkGeo](https://sparkgeo.com/) +* [Rob Emanuele](https://github.com/lossyrob) - [Microsoft](https://microsoft.com/) +* [Chris Holmes](https://github.com/cholmes) - [Planet](https://planet.com) and [Radiant Earth](https://www.radiant.earth/) + +#### PSC Membership + +A new PSC member can be nominated at any time. Voting for a new PSC is done by current active PSC members. PSC nominations are +generally given in recognition to very significant contributions to the specification or the broader ecosystem. PSC members +are not expected to be technical, and we hope to recognized contributions in documentation, outreach and evangelism. + +Nominated PSC members must recieve a majority of +1 vote’s from the PSC, and no -1’s. + +The initial PSC was selected by Chris Holmes, who was deemed the 'Benevolent Dictator for Life' for the bootstrapping phase. diff --git a/schema.json b/schema.json new file mode 100644 index 00000000..e69de29b From 65661d731eb15880e54eb1282f754b4a6f5974c1 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Tue, 20 Apr 2021 09:38:42 -0400 Subject: [PATCH 3/6] Remove CI step to init submodules --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 70cf716f..ccfa3f79 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,9 +27,6 @@ jobs: - image: circleci/node:12 steps: - checkout - - run: - name: init_submodules - command: git submodule update --init --recursive - save_cache: key: v0-repo-{{ .Branch }}-{{ .Revision }} paths: From db611739a333bc8ec6389b37e9825cc195287ac9 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Tue, 20 Apr 2021 09:39:03 -0400 Subject: [PATCH 4/6] Add PR template check that core spec was not changed. --- .github/pull_request_template.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d4e34f8a..fe8c00a7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -10,4 +10,5 @@ - [ ] This PR is made against the dev branch (all proposed changes except releases should be against dev, not master). - [ ] This PR has **no** breaking changes. +- [ ] This PR does not make any changes to the core spec in the `stac-spec` directory (these are included as a subtree and should be updated directly in [radiantearth/stac-spec](https://github.com/radiantearth/stac-spec)) - [ ] I have added my changes to the [CHANGELOG](https://github.com/radiantearth/stac-api-spec/blob/dev/CHANGELOG.md) **or** a CHANGELOG entry is not required. From e1cc9659c5cb669a121d21be574914a650c44cfd Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Tue, 4 May 2021 14:01:57 -0400 Subject: [PATCH 5/6] Fix extension links --- fragments/itemcollection/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fragments/itemcollection/README.md b/fragments/itemcollection/README.md index 1c851598..e0d6c115 100644 --- a/fragments/itemcollection/README.md +++ b/fragments/itemcollection/README.md @@ -31,7 +31,7 @@ This object describes a STAC ItemCollection. The fields `type` and `features` ar practices](../../stac-spec/best-practices.md#mixing-stac-versions) in mind. **stac_extensions**: A list of STAC content extensions the ItemCollection implements. The list contains URLs to the JSON Schema files it -can be validated against. For official [content extensions](../../stac-spec/extensions/README.md#list-of-content-extensions), a "shortcut" +can be validated against. For official [STAC extensions](https://stac-extensions.github.io/#list-of-stac-extensions), a "shortcut" can be used. This means you can specify the folder name of the extension, for example `single-file-stac` for the Single File STAC extension. This does *not* apply for [API extensions](../../extensions.md). If the versions of the extension and the item diverge, you can specify the URL of the JSON schema file. This list must only contain extensions that extend the ItemCollection itself, see the @@ -41,5 +41,5 @@ the 'Scope' column in the list of extensions. It must not contain extensions tha - The [Context Extension](../../item-search/README.md#context) adds additional fields to STAC ItemCollection relevant to their use as search results. -- The [Single File STAC Extension](../../stac-spec/extensions/single-file-stac/README.md) provides a set of Collections and Items +- The [Single File STAC Extension](https://github.com/stac-extensions/single-file-stac/blob/main/README.md) provides a set of Collections and Items as a single file catalog. From 2f81a0440d04fba78ae4f0ff83d8aa86a6e39d11 Mon Sep 17 00:00:00 2001 From: Jon Duckworth Date: Tue, 4 May 2021 15:35:10 -0400 Subject: [PATCH 6/6] Add CI check for changes to stac-spec directory --- .circleci/config.yml | 16 ++++++++++++++++ package.json | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ccfa3f79..f7a56114 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,6 +69,16 @@ jobs: command: | ssh-keyscan github.com >> ~/.ssh/known_hosts npm run publish-openapi -- $CIRCLE_TAG + check-core-changes: + working_directory: ~/stac + docker: + - image: circleci/node:12 + steps: + - *restore_repo + - *restore_dependencies + - run: + name: check-core-changes + command: npm run check-stac-spec-changes --compare-to=<< pipeline.git.base_revision >> workflows: version: 2 @@ -84,6 +94,12 @@ workflows: filters: tags: only: /^v.*/ + - check-core-changes: + requires: + - validate + filters: + tags: + only: /^v.*/ - publish: requires: - build diff --git a/package.json b/package.json index 902bb943..5c484cda 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "check-openapi-item-search": "spectral lint item-search/openapi.yaml --ruleset .circleci/.spectral.yml", "check-openapi-fragments": "spectral lint fragments/*/openapi.yaml --ruleset .circleci/.spectral-fragments.yml", "build-openapi": ".circleci/build-openapi.sh", - "publish-openapi": "node .circleci/publish.js" + "publish-openapi": "node .circleci/publish.js", + "check-stac-spec-changes": "git diff --quiet HEAD ${npm_config_compare_to} -- stac-spec" }, "dependencies": { "@stoplight/spectral": "^5.7.1",