package httpapi import "net/http" // ContractVersion is the version of the ratified contract this build serves // (`docs/architecture/14-api-contract/openapi.yaml`, `info.version`). // // It is a CONSTANT and it is the only place a non-streaming client learns which contract it is // talking to. While the major is `0` a differing MINOR carries breaking changes by design, so a // client generated against another one refuses to work and says so — which is why this must be // raised in the same commit as the code that implements a new minor, and never as a courtesy // afterwards. // ⚠ 0.11.0 is the ORDER FORM's minor (D39.196, unified backlog row 279), and while the canon on disk // still reads 0.10.0 the gate internal/gates.TestTheAnnouncedContractVersionIsTheOneTheCanonRatified // is RED — by its true cause, which is that the pair is not closed yet. The order was ratified by the // orchestrator on 05.09: the CODE lands first and the canon follows in the second act. The reverse // order was refused deliberately — errata 04.09-в is the day the canon moved first and the wire spent // a working day announcing a version it did not serve. const ContractVersion = "0.11.0" // Capabilities is what this deployment can do: one flat document, the same for every account. type Capabilities struct { // Pairs is what this deployment can translate, and what it merely knows about. Unavailable ones // are LISTED rather than omitted: "absent" and "listed as unavailable" are different facts to a // user waiting for one. Pairs []LanguagePair // IntakeEnabled is whether this deployment takes books at all. False is a read-only instance, // and without the field a client discovers that only by spending a user's upload. IntakeEnabled bool IntakeMaxBytes int64 // ExportFormats is what `POST /books/{bookId}/exports` accepts. Empty means none are built here, // which is the honest answer while the export path is not built (deferred to P8). ExportFormats []string // BankCorrectionsEnabled is whether this deployment serves the correction door, // `POST /books/{bookId}/bank/corrections`. False means the path answers 404 and a client does // not offer the correction UI — machine-readable so nobody learns it by failing a user's save // (canon §Capabilities; the same fact that decides the route's mount). BankCorrectionsEnabled bool // PageSizeDefault is how many rows a collection returns when `limit` is omitted. It is the // DEPLOYMENT's number rather than a constant of the contract, and every read path takes its // default from the same place this answers from. PageSizeDefault int } // LanguagePair is one direction, as the wire carries it. type LanguagePair struct { Source string Target string Available bool } type wireCapabilities struct { ContractVersion string `json:"contract_version"` LanguagePairs []wireLanguagePair `json:"language_pairs"` IntakeEnabled bool `json:"intake_enabled"` IntakeMaxBytes int64 `json:"intake_max_bytes"` ExportFormats []string `json:"export_formats"` BankCorrectionsEnabled bool `json:"bank_corrections_enabled"` PageSizeDefault int `json:"page_size_default"` } type wireLanguagePair struct { Source string `json:"source"` Target string `json:"target"` State string `json:"state"` } func (h *v0) capabilities(w http.ResponseWriter, r *http.Request) { if _, ok := principal(w, r); !ok { return } out := wireCapabilities{ ContractVersion: ContractVersion, LanguagePairs: make([]wireLanguagePair, 0, len(h.caps.Pairs)), IntakeEnabled: h.caps.IntakeEnabled, IntakeMaxBytes: h.caps.IntakeMaxBytes, ExportFormats: h.caps.ExportFormats, BankCorrectionsEnabled: h.caps.BankCorrectionsEnabled, PageSizeDefault: h.caps.PageSizeDefault, } if out.ExportFormats == nil { out.ExportFormats = []string{} // an empty collection is an empty array, never null } for _, p := range h.caps.Pairs { state := "unavailable" if p.Available { state = "available" } out.LanguagePairs = append(out.LanguagePairs, wireLanguagePair{Source: p.Source, Target: p.Target, State: state}) } h.writeJSON(w, r, http.StatusOK, out) }