# sfcrm query codec

This module is the L1 owner of the Salesforce-compatible query language and
HTTP response grammar used by the CRM dialect and sfcrm AppService. It is
stdlib-only: Runtime receives only the separately published neutral query
contract after the AppService adapter lowers this codec's typed request.

The codec owns:

- supported CRM API versions and query/queryAll/queryMore route matching;
- SOQL lexing, parsing and closed typed query intent;
- semi-join lowering as one correlated-membership operation;
- query windows, batch options and opaque locators;
- history-query projection;
- Salesforce query result, attributes, child-list and error envelopes.

It does not own authentication, delegation, Runtime admission, metadata,
permissions, database access, query execution, process lifecycle or service
deployment.

The executable query grammar follows the published neutral Runtime capability:
top-level selections support field paths plus `COUNT`, `SUM`, `AVG`, `MIN`, and
`MAX`; child selections and sort keys are field paths. The wider closed
function vocabulary is available only in predicate operands. A recognized
Salesforce function is not accepted in a clause whose neutral execution model
cannot represent it.

The first change publishes this mechanism without selecting it in a production
composition. The following ownership-flip change makes both the transitional
in-process dialect and the independent sfcrm AppService consume this module,
then deletes their competing query grammar implementations. A release tag must
exist before the AppService pins it; the AppService must never use a local
`replace` directive.

Run:

```bash
GOWORK=off go test ./...
GOWORK=off go test -race ./...
GOWORK=off go vet ./...
```

## NexusCRM response-size limit mapping

A typed `FailureResponseTooLarge` projects to HTTP 400 with `LIMIT_EXCEEDED`
in the existing Salesforce-shaped error array. `FailureExhausted` retains
HTTP 429 for existing callers, including Runtime concurrent admission. The
AppService selects the response-size category from the typed Runtime limit
kind, never by parsing error text. Both query and history use this projection.

This is an explicit NexusCRM extension for its internal encoded-response
budget, not a claim that Salesforce has the same byte ceiling or mapping.
The Salesforce v63 error envelope reference is
<https://developer.salesforce.com/docs/atlas.en-us.254.0.api_rest.meta/api_rest/errorcodes.htm>.
HTTP 429 denotes too many requests in a given period
(<https://www.rfc-editor.org/rfc/rfc6585#section-4>); an identical oversized
query needs a smaller result, not a delayed retry. HTTP 413 describes oversized
request content, not response content
(<https://www.rfc-editor.org/rfc/rfc9110#section-15.5.14>).

## Relative calendar dates

The query handler supports unquoted `TODAY`, `THIS_YEAR`, and
`LAST_N_DAYS:n` in comparisons with metadata-declared Date or DateTime fields.
Quoted strings keep their string type. L1 resolves the literal using one
clock sample and the authenticated user's `User.TimeZoneSidKey`; L0 receives
only ordinary typed comparisons. Date values use calendar dates; DateTime
boundaries use UTC instants derived from that user calendar, including DST.
`LAST_N_DAYS:n` includes today and ends at the captured current instant for
DateTime. Zero days means today so far. Invalid counts and out-of-calendar
ranges are rejected before execution.

The SF reference is the date-literal section of
<https://resources.docs.salesforce.com/latest/latest/en-us/sfdc/pdf/salesforce_soql_sosl.pdf>.
A query's clock and time zone are retained in its continuation locator. Later
pages revalidate current metadata and permissions but do not shift the date
window across midnight or a user time-zone change. Missing or invalid user
calendar facts fail explicitly; there is no host-local or UTC fallback.

The execution adapters supply current metadata field types, including formula
return types and supported parent/child relationships. This change does not
add fiscal literals, date-function comparisons, or new history-filter
capabilities. Retained parse-only bulk/search adapters lack authenticated
calendar context and reject relative literals explicitly before converting to
neutral queryspec; concrete date literals continue to work there.

Relative-date continuation locators require a complete original calendar anchor:
a nonzero supported instant and an explicit valid time-zone name. Missing/null
anchors, empty or invalid time zones, host-local zones and invalid instants are
rejected as HTTP 400 `INVALID_QUERY_LOCATOR` before metadata or query execution.
The shared date resolver also rejects incomplete supplied anchors when called
directly. Ordinary queries without relative dates retain legacy locator support.
