csapi

package
v0.0.0-...-d0d06e0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 41 Imported by: 0

Documentation

Overview

Stage 28 — OGC API Common Part 2 /collections metadata.

This is discovery only: collection entries point at the canonical CS API resource endpoints already implemented by semconnect. We intentionally do Stage 47 adds the first narrow /collections/{id}/items facade for the SystemEvent resource collection because CS API Part 2 tests exercise that collection advertisement explicitly.

Stage 24 — CS API Part 2 Control Streams read-side. A ControlStream describes a command channel for a System. v0.1 exposes the read resources the ETS exercises plus a small JSON POST helper used by the conformance harness to seed fixture data.

Package csapi: this file defines the v0.1 Datastream entity model.

Stage 13 — semstreams v1.0.0-beta.75 landed the `vocabulary/csapi` package with native OGC CS API type IRIs (`csapi.Datastream`) and CS API predicates. Stage 39's beta.91 pin split predicates into dotted internal names (`csapi.ProducedBy`) plus IRI boundary names (`csapi.ProducedByIRI`).

Stage 17 — PUT / DELETE / OPTIONS on /datastreams and /datastreams/{id}. Brings /datastreams parity with /systems (Stage 16) so the `create-replace-delete` conformance class claim is honest across both resource types the IUT implements.

Implementation re-uses the entity mutation helpers from the systems write path so write semantics and structured audit evidence stay symmetric.

Stage 35 — PATCH /datastreams/{id} parity for the CS API `conf/update` surface. Mirrors Stage 19's /systems PATCH stance: partial-update, no upsert, and no JSON Merge Patch null-as-delete at v0.1.

Stage 21 — CS API §8 Deployment resource. A Deployment links a System to a deployment context (location + valid time interval). Unlike /procedures, deployments DO carry geometry — a deployment is a physical placement of equipment at a location.

Endpoints at Stage 21: GET collection/item, POST, OPTIONS. PUT/DELETE/PATCH absent (ETS CRD/Update groups only target /systems — same Stage-20 reasoning).

**rdf:type IRI**: SSN's `Deployment` class IRI is `http://www.w3.org/ns/ssn/Deployment`, exported by semstreams as `sosa.SSNDeployment` since v1.0.0-beta.79.

Stage 21 — POST /deployments. JSON / geo+json Feature body only (no SensorML — SensorML doesn't have a Deployment encoding).

Distinct from /procedures:

  • rdf:type → ssnDeployment / sosa.SSNDeployment
  • Position triple emitted from `geometry` (deployments DO carry location, unlike procedures)

Distinct from /systems POST:

  • SensorML branch absent (no SensorML deployment encoding)
  • Different rdf:type + different entity-ID prefix

Package csapi implements the OGC API Connected Systems v1.0 HTTP gateway over the semstreams framework primitives.

The component implements:

Scope at v0.1 is fixed by ADR-S001 (docs/adr/001-cs-api-server-scope.md): Core + JSON + GeoJSON + SensorML + OMS + JSON-LD conformance classes, Accept-header content negotiation, anonymous-but-auditable identity (real auth lands behind the same middleware seam), single binary.

Stage 55 — CS API Part 2 Command Feasibility read-side.

Feasibility resources describe a command preflight/probe result for a ControlStream. v0.1 exposes read resources plus a JSON fixture POST helper used by the conformance harness; it does not execute commands or evaluate device-side feasibility.

Stage 20 — CS API §6 Procedure resource. Mirrors /systems read side: GET collection, GET item, OPTIONS, POST. Distinct from systems by rdf:type (sosa.Procedure vs sosa.SSNSystem) and by a spec-mandated lack of location — per OGC 23-001 /req/procedure/location, Procedures MUST NOT carry geometry. The JSON shape omits `geometry` accordingly.

**Why a separate file (vs. parameterized abstraction over /systems):** at Stage 20 we have only 2 resource types of this shape (Systems, Procedures). The user's CLAUDE.md "don't design for hypothetical future requirements; three similar lines is better than premature abstraction" applies. Stage 21+ (Deployments, SamplingFeatures, Properties) is when the 4-way duplication justifies extraction; we'll evaluate then.

**Endpoints landed at Stage 20:** GET/HEAD /procedures, GET/HEAD /procedures/{id}, POST /procedures, OPTIONS for both. PUT / DELETE / PATCH on /procedures are NOT landed here because the ETS CRD/Update test groups only target /systems — the existing conf/create-replace-delete + conf/update claims remain honest at /systems-only without expanding. If a real client (or a future ETS version) asks for procedure mutation, follow the Stage 16/19 pattern and ship them as a follow-up.

Stage 20 — POST /procedures. Mirrors POST /systems exactly except for:

  • rdf:type triple object → sosa.Procedure (not sosa.SSNSystem)
  • ID prefix → cfg.ProcedureIDPrefix
  • NO position triple (procedures don't carry location per /req/procedure/location)

Accepts the same four media types POST /systems does (sml+json / sensorml+json / json / geo+json) — the SensorML path for full spec parity (SOSA Procedure ↔ SensorML SimpleProcess), the Feature path for the ETS-style minimum-shape POST.

Stage 23 — CS API Property resource. Properties are SOSA ObservableProperty definitions used by Datastreams and Observations.

Endpoints at Stage 23: GET collection/item, POST, OPTIONS. PUT/DELETE/PATCH stay absent at v0.1 for the same OSH-bar scoping used by procedures, deployments, and sampling features.

Stage 22 — CS API Sampling Features resource. A sampling feature is a SOSA Sample / Feature-of-Interest proxy used by observations. Unlike procedures, sampling features carry first-class geometry.

Endpoints at Stage 22: GET collection/item, POST, OPTIONS. PUT / DELETE / PATCH stay absent at v0.1 for the same OSH-bar scoping used by procedures and deployments.

Stage 22 — POST /samplingFeatures. JSON / geo+json Feature body only. Sampling features carry first-class GeoJSON geometry, stored with the same position triple used by the other Feature-shaped resources until semstreams grows typed geometry primitives.

Stage 25 — CS API Part 2 System Events read-side. SystemEvent facts describe noteworthy changes or lifecycle notices about a System. v0.1 exposes the read resources the ETS exercises plus a JSON POST helper for conformance fixture seeding.

Stage 26 — System History read-side vendor extension. OGC 23-002 Annex A does not define a /conf/system-history class in the pinned ETS, but OSH exposes this surface. v0.1 serves the current System description as the single available historical revision.

Stage 16 — PUT / DELETE / OPTIONS on /systems and /systems/{id}. Closes the CS API §7.6 create-replace-delete conformance class.

Stage 37 moved the write path onto semstreams entity-level mutation subjects, retiring the prior delete-all + add-batch partial-erasure window.

Stage 19 — PATCH /systems/{id} for the CS API `conf/update` conformance class. Body shape mirrors POST/PUT (GeoJSON Feature), but semantics are partial-update: only fields present in the body get replaced; fields absent are left alone.

We do NOT implement JSON Merge Patch (RFC 7396) null-as-delete semantics at v0.1. A future stage can add that — the ETS doesn't exercise it. Documented in the handler doc comment + OAS3.

Index

Constants

View Source
const (
	ControlStreamTypeIRI = csapivocab.ControlStream
	CommandTypeIRI       = csapivocab.Command

	PredControlStreamSystem  = csapivocab.ControlsSystem
	PredCommandControlStream = csapivocab.PartOfControlStream
)
View Source
const (
	// semstreams does not yet expose a CS API Feasibility vocabulary term.
	// Keep the local type IRI explicit so it is easy to retire when the
	// framework grows one.
	FeasibilityTypeIRI = csapivocab.Feasibility

	PredFeasibilityControlStream = csapivocab.FeasibilityControlStream
)
View Source
const (
	SystemEventTypeIRI = csapivocab.SystemEvent

	PredSystemEventSystem = csapivocab.EventForSystem
)
View Source
const (
	PredSystemPosition = sensorml.PredPosition
	PredSystemUID      = sensorml.PredUniqueID
)

PredSystemPosition and PredSystemUID are the framework-owned SensorML predicates semconnect uses for CS API uid / geometry round-trips. They are kept behind gateway-local names because Feature-shaped resources (deployments, sampling features, etc.) use the same graph predicates even when their HTTP representation is not SensorML.

View Source
const DatastreamTypeIRI = csapi.Datastream

DatastreamTypeIRI is the rdf:type Object value for Datastream entities. Stage 13: aliases csapi.Datastream (the framework's canonical IRI from v1.0.0-beta.75 onward). Kept as a named const so handler /test code reads naturally without leaking the package import everywhere.

View Source
const PredDatastreamSchema = csapi.HasResultSchema

PredDatastreamSchema links a Datastream to the first-class csapi:SWESchemaDocument artifact entity that stores the canonical SWE Common result schema bytes. Stage 42 retires the previous gateway-local JSON predicate bridge and aliases beta.91's dotted relationship predicate.

View Source
const PredDatastreamSystem = csapi.ProducedBy

PredDatastreamSystem links a Datastream entity to the 6-part SemStreams entity ID of the System (Sensor) that produces it. Stage 39: aliases beta.91's dotted csapi.ProducedBy.

Variables

This section is empty.

Functions

func IdentityMiddleware

func IdentityMiddleware(next http.Handler) http.Handler

IdentityMiddleware wraps next so every request carries an Identity in its context. v0.1 records X-Forwarded-* headers from a trusted reverse proxy but does not verify anything. Replacing the body of this function with a JWT / mTLS verifier is the entire mechanical change to add real auth — handlers stay unchanged.

func SupportedMedia

func SupportedMedia(fam ResourceFamily) []string

SupportedMedia returns the supported set for fam — for use in 406 bodies.

func WriteNotAcceptable

func WriteNotAcceptable(w http.ResponseWriter, fam ResourceFamily)

WriteNotAcceptable writes a 406 with the family's supported encoding list.

func WriteNotAcceptableWith

func WriteNotAcceptableWith(w http.ResponseWriter, supported []MediaType)

WriteNotAcceptableWith writes a 406 with an explicit supported list, used when the resource cannot satisfy its family's full claim (e.g. a System item missing rdf:type cannot be SensorML- or JSON-LD-rendered even though FamilySystemItem promises both).

Types

type Component

type Component struct {
	// contains filtered or unexported fields
}

Component is the cs-api gateway. It implements:

  • component.Discoverable (framework discovery)
  • component.LifecycleComponent (Initialize / Start / Stop)
  • gateway.Gateway (RegisterHTTPHandlers)

func New

func New(cfg Config, nats natsRequester, logger *slog.Logger) (*Component, error)

New constructs a Component. The constructor is test-friendly: pass a mock natsRequester and a nil logger to drive handlers from unit tests.

func (*Component) ConfigSchema

func (c *Component) ConfigSchema() component.ConfigSchema

func (*Component) DataFlow

func (c *Component) DataFlow() component.FlowMetrics

func (*Component) Health

func (c *Component) Health() component.HealthStatus

func (*Component) Initialize

func (c *Component) Initialize() error

func (*Component) InputPorts

func (c *Component) InputPorts() []component.Port

func (*Component) Meta

func (c *Component) Meta() component.Metadata

func (*Component) OutputPorts

func (c *Component) OutputPorts() []component.Port

func (*Component) RegisterHTTPHandlers

func (c *Component) RegisterHTTPHandlers(prefix string, mux *http.ServeMux)

RegisterHTTPHandlers registers the cs-api v0.1 endpoint set on mux under prefix. ServiceManager calls this with a per-component prefix; the standalone Start() path calls it with "".

Every handler is wrapped by the middleware chain so:

  • Identity is always populated in the request context
  • request count + lastActivity update for /metrics + /health
  • panics are recovered and surfaced as 500

func (*Component) Start

func (c *Component) Start(ctx context.Context) error

func (*Component) Stop

func (c *Component) Stop(timeout time.Duration) error

type Config

type Config struct {
	// BindAddress is used only in StandaloneServer mode. Production deployments
	// embed under semstreams' service.ServiceManager and leave it blank.
	BindAddress string `json:"bind_address"`

	// StandaloneServer makes the component manage its own *http.Server in
	// Start(). False is the production default — ServiceManager owns the
	// listener and calls RegisterHTTPHandlers on its shared mux.
	StandaloneServer bool `json:"standalone_server"`

	// QueryTimeout caps every NATS request/reply the gateway issues.
	// Tuned per ADR-S001's expectation that reads stay sub-second.
	QueryTimeout time.Duration `json:"query_timeout"`

	// ReadHeaderTimeout / ReadTimeout / WriteTimeout / IdleTimeout shape the
	// standalone HTTP server. Production deployments tune at the reverse
	// proxy instead.
	ReadHeaderTimeout time.Duration `json:"read_header_timeout"`
	ReadTimeout       time.Duration `json:"read_timeout"`
	WriteTimeout      time.Duration `json:"write_timeout"`
	IdleTimeout       time.Duration `json:"idle_timeout"`

	// MaxRequestBytes caps request body size. POST endpoints will reject
	// larger bodies with 413.
	MaxRequestBytes int64 `json:"max_request_bytes"`

	// DefaultListLimit is the page size returned by collection endpoints
	// when the client did not pass ?limit=. CS API spec leaves this to the
	// implementation.
	DefaultListLimit int `json:"default_list_limit"`

	// MaxListLimit caps client-supplied ?limit= so a single request cannot
	// trigger an unbounded predicate scan.
	MaxListLimit int `json:"max_list_limit"`

	// PublishTimeout caps observation publishes (POST endpoints).
	// Kept separate from QueryTimeout so a slow JetStream ack does not
	// block independently-budgeted reads.
	PublishTimeout time.Duration `json:"publish_timeout"`

	// ObservationsStream is the JetStream stream name that captures
	// observation publishes. The cs-api gateway EnsureStream's it at
	// Start() so the first POST does not race the stream's creation.
	ObservationsStream string `json:"observations_stream"`

	// ObservationsSubjectPrefix shapes the per-observation publish subject.
	// A POST /datastreams/{id}/observations becomes
	// "<prefix>.<datastream_id>". Trailing dot is added automatically.
	ObservationsSubjectPrefix string `json:"observations_subject_prefix"`

	// ObservationsMaxAge bounds how long observation messages live in the
	// stream. 30 days is the v0.1 default — auditors get a window,
	// consumers that lag can replay. Tune per deployment.
	ObservationsMaxAge time.Duration `json:"observations_max_age"`

	// ObservationsMaxBytes caps the stream's on-disk size. It must be positive
	// so a runaway client cannot fill the disk to the JetStream account limit.
	ObservationsMaxBytes int64 `json:"observations_max_bytes"`

	// ObservationsReplicas controls JetStream replica count. 1 is fine for
	// single-node dev/test; production HA uses 3.
	ObservationsReplicas int `json:"observations_replicas"`

	// SchemaArtifactsBucket is the NATS ObjectStore bucket that holds
	// canonical SWE schema documents referenced by first-class graph artifact
	// entities. The bucket is ensured during Start().
	SchemaArtifactsBucket string `json:"schema_artifacts_bucket"`

	// SchemaArtifactsMaxBytes is the bucket-level storage cap for schema
	// artifacts. 0 means unlimited, matching JetStream ObjectStore defaults.
	SchemaArtifactsMaxBytes int64 `json:"schema_artifacts_max_bytes"`

	// SchemaArtifactsReplicas controls ObjectStore replica count. Keep aligned
	// with the NATS cluster topology; dev/test defaults to 1.
	SchemaArtifactsReplicas int `json:"schema_artifacts_replicas"`

	// SystemIDPrefix is the 5-part SemStreams entity ID prefix the gateway
	// uses when minting IDs for POST /systems. The 6th token is derived
	// from the SensorML uniqueId (or a UUID if uniqueId is absent).
	//
	// SemStreams entity IDs are exactly 6 dotted tokens
	// (org.platform.domain.system.type.instance per graph-ingest's
	// entityIDRegex). Validate() enforces that the prefix is exactly 5
	// tokens of valid characters; bad prefixes are a deployment-time
	// configuration error, not a runtime one.
	//
	// Default `c360.semconnect.systems.csapi.system` — operators set this
	// per deployment so cross-tenant entity IDs don't collide.
	SystemIDPrefix string `json:"system_id_prefix"`

	// DatastreamIDPrefix is the analogous 5-part prefix for POST /datastreams.
	// Defaults to `c360.semconnect.systems.csapi.datastream` so the 5th
	// token cleanly separates systems from datastreams under the same
	// deployment.
	DatastreamIDPrefix string `json:"datastream_id_prefix"`

	// ProcedureIDPrefix is the 5-part prefix for POST /procedures.
	// Stage 20 — separate from SystemIDPrefix so cross-tenant procedure
	// IDs land under a distinct 5th-token namespace.
	ProcedureIDPrefix string `json:"procedure_id_prefix"`

	// DeploymentIDPrefix is the 5-part prefix for POST /deployments.
	// Stage 21.
	DeploymentIDPrefix string `json:"deployment_id_prefix"`

	// SamplingFeatureIDPrefix is the 5-part prefix for POST /samplingFeatures.
	// Stage 22.
	SamplingFeatureIDPrefix string `json:"sampling_feature_id_prefix"`

	// PropertyIDPrefix is the 5-part prefix for POST /properties.
	// Stage 23.
	PropertyIDPrefix string `json:"property_id_prefix"`

	// ControlStreamIDPrefix is the 5-part prefix for POST /controlstreams.
	// Stage 24.
	ControlStreamIDPrefix string `json:"controlstream_id_prefix"`

	// CommandIDPrefix is the 5-part prefix for POST /commands.
	// Stage 51.
	CommandIDPrefix string `json:"command_id_prefix"`

	// FeasibilityIDPrefix is the 5-part prefix for POST /feasibility.
	// Stage 55.
	FeasibilityIDPrefix string `json:"feasibility_id_prefix"`

	// SystemEventIDPrefix is the 5-part prefix for POST /systemEvents and
	// /systems/{id}/events. Stage 25.
	SystemEventIDPrefix string `json:"system_event_id_prefix"`

	// SchemaArtifactIDPrefix is the 5-part prefix for SWE schema artifact
	// entities. Datastreams relate to these via csapi.HasResultSchema and
	// ControlStreams via csapi.HasCommandSchema.
	SchemaArtifactIDPrefix string `json:"schema_artifact_id_prefix"`
}

Config tunes the cs-api gateway component. Defaults satisfy a development deployment; production deployments override via the JSON config file.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a fully-populated Config. Stage 2 binaries call this and then overlay parsed JSON.

func (*Config) ApplyDefaults

func (c *Config) ApplyDefaults()

ApplyDefaults overlays zero-valued fields with DefaultConfig values. Order matters: caller parses JSON into a Config, then calls ApplyDefaults, then Validate.

func (*Config) Validate

func (c *Config) Validate() error

Validate rejects nonsensical combinations. Called after ApplyDefaults.

type Datastream

type Datastream struct {
	ID               string             `json:"id"`
	Type             string             `json:"type"` // "Datastream"
	Name             string             `json:"name,omitempty"`
	Description      string             `json:"description,omitempty"`
	System           string             `json:"system,omitempty"`           // 6-part entity ID
	SystemID         string             `json:"system@id,omitempty"`        // CS API Part 2 shape
	SystemLink       *link              `json:"system@link,omitempty"`      // CS API Part 2 shape
	OutputName       string             `json:"outputName,omitempty"`       // CS API Part 2 shape
	ObservedProperty string             `json:"observedProperty,omitempty"` // IRI
	ObservedProps    []observedProperty `json:"observedProperties,omitempty"`
	PhenomenonTime   string             `json:"phenomenonTime,omitempty"`
	ResultTime       string             `json:"resultTime,omitempty"`
	Formats          []string           `json:"formats,omitempty"`
	ResultType       string             `json:"resultType,omitempty"`
	Schema           json.RawMessage    `json:"schema,omitempty"` // SWE Common DataRecord JSON
	Links            []link             `json:"links"`
}

Datastream is the v0.1 JSON shape for CS API §10 Datastream resources. Fields are the subset semstreams' vocabulary can losslessly round-trip today; deferred fields are listed in the package doc comment above.

type Identity

type Identity struct {
	// Subject is the verified principal identifier (sub claim, mTLS CN, …)
	// when authentication is on, or empty when anonymous.
	Subject string

	// Forwarded carries trust-on-faith hints from an upstream reverse proxy
	// (X-Forwarded-User, X-Forwarded-Email). At v0.1 these are recorded for
	// audit only — handlers must not make authorization decisions on them.
	Forwarded map[string]string

	// Verified is true only when the server itself validated the identity.
	// At v0.1 this is always false.
	Verified bool
}

Identity is the authenticated principal for an HTTP request.

At v0.1 every request carries Anonymous(). The middleware boundary is in place so a future ADR can drop in JWT / mTLS verification without touching handler code: handlers always read Identity from the context, and audit headers always flow through to NATS publishes regardless of how the identity was established.

func Anonymous

func Anonymous() Identity

Anonymous returns the v0.1 default identity attached to every request.

func IdentityFrom

func IdentityFrom(ctx context.Context) Identity

IdentityFrom returns the Identity attached to ctx. The zero-value Anonymous identity is returned if no middleware has run — but in production every request flows through WithIdentity first, so handlers can rely on it.

func (Identity) AuditHeaders

func (id Identity) AuditHeaders() map[string]string

AuditHeaders returns the headers a NATS publish should carry so downstream consumers can record who triggered the publish. Always returns a non-nil map; callers can safely merge into it.

First consumer lands at Stage 3 (POST /datastreams/{id}/observations) when the publish call needs to ship these onto the BaseMessage envelope. The seam lives here at Stage 2 so the audit trail starts honest from the first mutation, no handler edit required.

type MediaType

type MediaType string

MediaType is a CS API response encoding the server can produce.

const (
	MediaJSON    MediaType = "application/json"
	MediaJSONLD  MediaType = "application/ld+json"
	MediaGeoJSON MediaType = "application/geo+json"
	// SensorML 2.0 JSON encoding. Per CS API §11.7 the canonical media
	// type is `application/sml+json`; `application/sensorml+json` was a
	// pre-Stage-14 longer-name choice. We now serve the spec form;
	// MediaSensorMLLegacy is the long-name alias the supported() table
	// still advertises for backward compat with anything that learned
	// the long form from older /api docs or returned 406 bodies.
	MediaSensorML       MediaType = "application/sml+json"
	MediaSensorMLLegacy MediaType = "application/sensorml+json"
	MediaOMS            MediaType = "application/om+json"
	MediaSWEJSON        MediaType = "application/swe+json"
	MediaSWECsv         MediaType = "application/swe+csv"
	MediaSWEBinary      MediaType = "application/swe+binary"
	// OAS3 content types per OpenAPI Initiative registration (2021).
	// Used by /api (Stage 12) — Swagger UI / Redoc / openapi-generator
	// all prefer the +json form; the YAML form is the raw embedded body.
	MediaOAS3JSON MediaType = "application/vnd.oai.openapi+json;version=3.0"
	MediaOAS3YAML MediaType = "application/vnd.oai.openapi;version=3.0"
)

func Negotiate

func Negotiate(accept string, fam ResourceFamily) (MediaType, bool)

Negotiate picks the response MediaType for an Accept header against fam's supported set. Returns (chosen, true) on success, ("", false) on 406 — the caller writes the 406 response (with the supported set in its body) so this function stays pure.

HTTP handlers MUST use NegotiateRequest, not Negotiate — Negotiate alone skips the Common Part 1 `?f=` override and silently regresses the conformance class. Negotiate stays exported for the negotiation_test.go table (string-in / MediaType-out is trivial to drive in tables) and for any future non-HTTP negotiation caller.

func NegotiateRequest

func NegotiateRequest(r *http.Request, fam ResourceFamily) (MediaType, bool)

NegotiateRequest is Negotiate's request-aware sibling. Per Common Part 1 Conformance class "JSON" (req/json/content), the `?f=<short>` query parameter overrides Accept when present. Precedence is intentional: an explicit `?f=` short-name that does not map to fam's supported set 406s rather than falling through to Accept, because the override is a deliberate client signal.

`?f=` absent, empty, or whitespace-only → fall back to Negotiate(Accept, fam). There is no `?f=` value that forces the family default independent of Accept — use `?f=<short>` explicitly if that's the intent.

Unknown short names (not in shortMediaNames) 406, with the family's supported list advertised in the 406 body just like any other negotiation failure — clients sending `?f=html` against a JSON-only server need to see that html is not on offer.

type ResourceFamily

type ResourceFamily int

ResourceFamily groups endpoints that share the same negotiable encoding set. Collection and item endpoints of the same kind do NOT share a family if their supported sets differ (e.g. there is no SensorML SystemCollection type, so the collection endpoint narrows). Adding a family is preferable to inline-narrowing in handlers because the 406 body advertises the correct supported set automatically.

const (
	FamilySystemItem            ResourceFamily = iota // GET /systems/{id}
	FamilySystemCollection                            // GET /systems
	FamilyDatastreamItem                              // GET /datastreams/{id}
	FamilyDatastreamCollection                        // GET /datastreams
	FamilyObservationCollection                       // GET /datastreams/{id}/observations (Stage 11)
	FamilySpatial
	FamilyService // /, /conformance
	FamilyAPI     // GET /api (Stage 12) — OAS3 service definition

	// FamilyProcedureCollection — GET /procedures. Stage 20 added the
	// resource; Stage 20.1 added MediaGeoJSON to the supported set
	// after the ETS's procedureFeatureHasGeoJsonSchemaAndMapping
	// assertion surfaced that `Accept: application/geo+json` is
	// expected to return a FeatureCollection (every Feature with
	// `geometry: null` per /req/procedure/location).
	FamilyProcedureCollection
	// FamilyProcedureItem — GET /procedures/{id}. JSON + SensorML. A
	// Procedure naturally maps to SensorML SimpleProcess / AggregateProcess.
	FamilyProcedureItem

	// FamilyDeploymentCollection — GET /deployments (Stage 21). JSON +
	// geo+json supported; deployments DO carry geometry (deploy site).
	FamilyDeploymentCollection
	// FamilyDeploymentItem — GET /deployments/{id}. JSON-only.
	FamilyDeploymentItem

	// FamilySamplingFeatureCollection — GET /samplingFeatures (Stage 22).
	// JSON + geo+json supported; sampling features carry first-class
	// geometry in the CS API Feature shape.
	FamilySamplingFeatureCollection
	// FamilySamplingFeatureItem — GET /samplingFeatures/{id}. JSON-only.
	FamilySamplingFeatureItem

	// FamilyPropertyCollection — GET /properties (Stage 23). JSON-only
	// at v0.1; the upstream schema is SensorML DerivedProperty-shaped
	// JSON, but this gateway returns the same JSON subset style used by
	// the other OSH-bar registry resources.
	FamilyPropertyCollection
	// FamilyPropertyItem — GET /properties/{id}. JSON-only.
	FamilyPropertyItem

	// FamilyControlStreamCollection — GET /controlstreams and
	// /systems/{id}/controlstreams (Stage 24). JSON-only at v0.1.
	FamilyControlStreamCollection
	// FamilyControlStreamItem — GET /controlstreams/{id}. JSON-only.
	FamilyControlStreamItem

	// FamilySystemEventCollection — GET /systemEvents and
	// /systems/{id}/events (Stage 25). JSON-only at v0.1.
	FamilySystemEventCollection
	// FamilySystemEventItem — GET /systemEvents/{id} and
	// /systems/{systemID}/events/{eventID}. JSON-only.
	FamilySystemEventItem

	// FamilyFeasibilityCollection — GET /feasibility and
	// /controlstream/{id}/feasibility (Stage 55). JSON-only at v0.1.
	FamilyFeasibilityCollection
	// FamilyFeasibilityItem — GET /feasibility/{id}. JSON-only.
	FamilyFeasibilityItem
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL