@webex/http-core 3.12.0-next.7 → 3.12.0-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.repo-context.json +590 -0
- package/.sdd/manifest.json +362 -0
- package/AGENTS.md +219 -0
- package/docs/adr/0001-fork-xhr-for-frozen-object-environments.md +111 -0
- package/docs/adr/index.md +26 -0
- package/docs/architecture.md +335 -0
- package/docs/getting-started.md +108 -0
- package/docs/index.md +46 -0
- package/docs/specs/README.md +79 -0
- package/package.json +8 -8
- package/schemas/repo-context.schema.json +796 -0
- package/src/docs/README.md +485 -0
- package/src/request/docs/README.md +481 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: ADR
|
|
3
|
+
title: ADR-0001 - Fork xhr to support fully object-frozen environments
|
|
4
|
+
description: The browser transport uses a vendored fork of naugtur/xhr, held close to upstream, because the published package does not work where the global object graph is frozen.
|
|
5
|
+
tags: [adr]
|
|
6
|
+
timestamp: 2026-09-23T00:00:00Z
|
|
7
|
+
status: accepted
|
|
8
|
+
---
|
|
9
|
+
<!-- sdd-generated-metadata
|
|
10
|
+
doc_kind: standing-doc
|
|
11
|
+
generated_from: adr@0.3.0
|
|
12
|
+
generated_by: claude-code
|
|
13
|
+
approved_by: pending
|
|
14
|
+
updated_at: 2026-09-23T06:29:48Z
|
|
15
|
+
validation_status: pass-with-warnings
|
|
16
|
+
-->
|
|
17
|
+
|
|
18
|
+
# ADR-0001 - Fork `xhr` to support fully object-frozen environments
|
|
19
|
+
|
|
20
|
+
| Field | Value |
|
|
21
|
+
| ------------- | ----------------------------------------------------------------------- |
|
|
22
|
+
| Status | Accepted |
|
|
23
|
+
| Decision date | Not recorded in the codebase |
|
|
24
|
+
| Deciders | Not recorded in the codebase |
|
|
25
|
+
| Supersedes | N/A |
|
|
26
|
+
| Superseded by | N/A |
|
|
27
|
+
|
|
28
|
+
## Context
|
|
29
|
+
|
|
30
|
+
The browser transport needs an `XMLHttpRequest` wrapper that presents the same option vocabulary as
|
|
31
|
+
the Node `request` library, so that one public API works on both platforms. The `naugtur/xhr`
|
|
32
|
+
package provides that wrapper.
|
|
33
|
+
|
|
34
|
+
Some environments the SDK must run in freeze the object graph completely. `src/lib/xhr.js` records
|
|
35
|
+
the problem directly in its header: the fork exists "to support environments with full object
|
|
36
|
+
freezing; namely, SalesForce's Aura and Locker environment." The upstream package does not function
|
|
37
|
+
under that constraint.
|
|
38
|
+
|
|
39
|
+
## Decision
|
|
40
|
+
|
|
41
|
+
Vendor a fork of `naugtur/xhr` into the repository at `src/lib/xhr.js`, and have the browser
|
|
42
|
+
transport import it from there rather than from `node_modules`. `src/request/request.shim.js`
|
|
43
|
+
imports `xhr` from `../lib/xhr`, so no browser request path reaches the upstream package.
|
|
44
|
+
|
|
45
|
+
The fork keeps upstream's code style deliberately. Its header states the rule: "Maintain the original
|
|
46
|
+
code style of https://github.com/naugtur/xhr since we're trying to diverge as little as possible."
|
|
47
|
+
The file carries a whole-file `/* eslint-disable */` so repository lint rules do not force it away
|
|
48
|
+
from that style, and it keeps upstream's `var` declarations and `'use strict'` prologue.
|
|
49
|
+
|
|
50
|
+
Its runtime dependencies are declared as ordinary dependencies of this package: `global`,
|
|
51
|
+
`is-function`, `parse-headers`, and `xtend` in `package.json` exist to serve this file.
|
|
52
|
+
|
|
53
|
+
## Why
|
|
54
|
+
|
|
55
|
+
A fork was required because the constraint is environmental, not stylistic — the package simply does
|
|
56
|
+
not run where the object graph is frozen, and no configuration of the published package avoids that.
|
|
57
|
+
|
|
58
|
+
Holding the fork close to upstream is the second half of the decision, and it is what makes the first
|
|
59
|
+
half sustainable: a fork that drifts cannot absorb upstream fixes, and this file implements the
|
|
60
|
+
error, timeout, abort, and header-parsing behavior every browser request in the SDK depends on.
|
|
61
|
+
|
|
62
|
+
## Alternatives considered
|
|
63
|
+
|
|
64
|
+
| Alternative | Why it was not selected |
|
|
65
|
+
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
66
|
+
| Depend on the upstream `naugtur/xhr` package | It does not work in environments that fully freeze objects, which the SDK must support |
|
|
67
|
+
| Reformat the fork to repository style | Rejected implicitly by the file's own instruction to diverge as little as possible, and by its `eslint-disable` |
|
|
68
|
+
|
|
69
|
+
No other alternatives are recorded in the codebase. Rationale beyond what the file states is not
|
|
70
|
+
reconstructed here.
|
|
71
|
+
|
|
72
|
+
## Consequences
|
|
73
|
+
|
|
74
|
+
**Positive:**
|
|
75
|
+
|
|
76
|
+
- Browser requests work in fully object-frozen environments.
|
|
77
|
+
- The browser transport keeps the same option vocabulary as the Node transport, so one public API
|
|
78
|
+
serves both platforms.
|
|
79
|
+
|
|
80
|
+
**Negative / tradeoffs:**
|
|
81
|
+
|
|
82
|
+
- The repository owns third-party code it must maintain, including its security posture.
|
|
83
|
+
- Upstream fixes are not received automatically; they must be ported deliberately.
|
|
84
|
+
- The file is excluded from repository lint rules, so ordinary static analysis does not cover it.
|
|
85
|
+
- Four dependencies in `package.json` exist only to serve this one file.
|
|
86
|
+
|
|
87
|
+
## Constraint on future changes
|
|
88
|
+
|
|
89
|
+
Keep `src/lib/xhr.js` as close to its upstream original as the frozen-object requirement allows.
|
|
90
|
+
Do not reformat it, do not re-enable repository lint rules on it, and do not refactor it to
|
|
91
|
+
repository conventions. Port upstream changes as discrete, reviewable diffs.
|
|
92
|
+
|
|
93
|
+
Do not switch the browser transport to the upstream package or to another XHR wrapper without first
|
|
94
|
+
confirming the replacement works under full object freezing.
|
|
95
|
+
|
|
96
|
+
## Follow-up
|
|
97
|
+
|
|
98
|
+
- [ ] Record the upstream commit or version this fork is based on, so future ports have a baseline
|
|
99
|
+
- [ ] Confirm whether the frozen-object environments named in the file header are still supported targets
|
|
100
|
+
|
|
101
|
+
## Revisit when
|
|
102
|
+
|
|
103
|
+
- The named frozen-object environments are no longer supported targets.
|
|
104
|
+
- Upstream `naugtur/xhr`, or a maintained alternative, works under full object freezing.
|
|
105
|
+
- The browser transport moves off `XMLHttpRequest`, which would remove the dependency entirely.
|
|
106
|
+
|
|
107
|
+
## References
|
|
108
|
+
|
|
109
|
+
- `src/lib/xhr.js` — the fork and its stated rationale
|
|
110
|
+
- `src/request/request.shim.js` — the only importer
|
|
111
|
+
- `package.json` — the four dependencies that exist to serve the fork
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!-- sdd-generated-metadata
|
|
2
|
+
doc_kind: standing-doc
|
|
3
|
+
generated_from: adr-index@0.3.0
|
|
4
|
+
generated_by: claude-code
|
|
5
|
+
approved_by: pending
|
|
6
|
+
updated_at: 2026-09-23T06:29:48Z
|
|
7
|
+
validation_status: pass-with-warnings
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# Architectural decision records
|
|
11
|
+
|
|
12
|
+
Numbered, append-only records of structural decisions affecting this repository
|
|
13
|
+
and its documentation. Add a concrete ADR (for example, `0042-cache-policy.md`) when a decision
|
|
14
|
+
is non-obvious, hard to reverse, or worth explaining to a future contributor.
|
|
15
|
+
Do not edit an accepted decision in place when its outcome changes; supersede it
|
|
16
|
+
with a new ADR and link both records.
|
|
17
|
+
|
|
18
|
+
## Index
|
|
19
|
+
|
|
20
|
+
- [0001 — Fork `xhr` to support fully object-frozen environments](0001-fork-xhr-for-frozen-object-environments.md)
|
|
21
|
+
|
|
22
|
+
Add new entries as ADRs are accepted. Keep this list in numeric order.
|
|
23
|
+
|
|
24
|
+
Each ADR should state its context, decision, alternatives, consequences, and
|
|
25
|
+
the condition that would cause the team to revisit it. Record the deciders,
|
|
26
|
+
any superseded decision, and the constraint future changes must preserve.
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Architecture
|
|
3
|
+
title: '@webex/http-core architecture'
|
|
4
|
+
description: Repository-wide boundaries, resources, interactions, dependencies, and cross-cutting architecture.
|
|
5
|
+
tags: [architecture]
|
|
6
|
+
---
|
|
7
|
+
<!-- sdd-generated-metadata
|
|
8
|
+
doc_kind: standing-doc
|
|
9
|
+
generated_from: architecture@0.3.0
|
|
10
|
+
generated_by: claude-code
|
|
11
|
+
approved_by: pending
|
|
12
|
+
updated_at: 2026-09-23T06:29:48Z
|
|
13
|
+
validation_status: pass-with-warnings
|
|
14
|
+
-->
|
|
15
|
+
|
|
16
|
+
# @webex/http-core architecture
|
|
17
|
+
|
|
18
|
+
Canonical repository-wide architecture for the core HTTP client of the Webex JS SDK. This document
|
|
19
|
+
owns facts that span the package's modules. Link to the owning module, ADR, or native contract
|
|
20
|
+
instead of duplicating owner-local detail.
|
|
21
|
+
|
|
22
|
+
Related context: [specification registry](specs/README.md) ·
|
|
23
|
+
[repository agent instructions](../AGENTS.md)
|
|
24
|
+
|
|
25
|
+
## Applicability
|
|
26
|
+
|
|
27
|
+
Sections preceded by an `Include if` comment are conditional. Retain a
|
|
28
|
+
conditional section only when repository evidence satisfies its condition.
|
|
29
|
+
|
|
30
|
+
| Condition ID | Status | Evidence or reason | Owned section |
|
|
31
|
+
| ------------------------------------ | ---------- | ---------------------------------------------------------------------------------- | ----------------------------------- |
|
|
32
|
+
| `repo.owns_datastore` | N/A | No datastore, ORM, migration directory, or connection configuration; `package.json` declares no database dependency | Repository data and schema |
|
|
33
|
+
| `repo.holds_client_state` | N/A | No state-store library; the only stateful objects are per-request emitters created in `src/request/index.js` and discarded with the request | Client state model |
|
|
34
|
+
| `repo.components_interact` | Applicable | `src/index.js` composes the interceptor chain executed in `src/request/utils.ts`, and transports emit progress on caller-held emitters | Dependency and interaction topology |
|
|
35
|
+
| `repo.domain_data_across_components` | N/A | The package owns no domain entities; it transports caller-supplied payloads | Object and data ownership |
|
|
36
|
+
| `repo.caches_data` | N/A | No cache layer, TTL, or memoization exists in `src/` | Caching catalog |
|
|
37
|
+
| `repo.observability_convention` | Applicable | Injectable logger plus the `ENABLE_VERBOSE_NETWORK_LOGGING` gate in `src/lib/interceptor.js`, and the level-differentiated logging in `src/request/request.shim.js` | Observability patterns |
|
|
38
|
+
| `repo.deploys_to_infra` | N/A | Published library with no deployment descriptor, container, or runtime entry point; `package.json` exposes only build, test, and publish scripts | Runtime and infrastructure |
|
|
39
|
+
| `repo.shared_base_libs` | Applicable | ESLint, Babel, and Jest configuration are all inherited from workspace config packages via `.eslintrc.js`, `babel.config.js`, `jest.config.js` | Shared and base libraries |
|
|
40
|
+
| `repo.is_monorepo` | N/A | The onboarding scope is this single package with one build root; the surrounding workspace is external context | Package map and dependencies |
|
|
41
|
+
| `repo.multi_platform` | Applicable | `package.json` swaps the Node transport for the browser shim; `src/request/request.js` and `src/request/request.shim.js` | Platform matrix |
|
|
42
|
+
| `repo.published_package` | Applicable | `package.json` declares `main`, `browser`, and a `deploy:npm` script | Release and versioning |
|
|
43
|
+
| `repo.embedded_in_host` | N/A | Consumed as a dependency, not mounted into a host application | Host integration and theming |
|
|
44
|
+
| `repo.exposes_commands_or_artifacts` | Applicable | `package.json` declares no bin, but its scripts are the committed build, test, and publish entry points and build:src emits the published dist artifact | Commands and generated artifacts |
|
|
45
|
+
| `repo.cross_repo_deps_material` | N/A | Every internal dependency resolves inside the same workspace; the rest are public npm packages per `package.json` | Cross-repository topology |
|
|
46
|
+
| `repo.security_arch_warranted` | Applicable | The package constructs `Authorization` headers and controls cookie credentials in `src/request/request.shim.js` and `src/request/request.js` | Security architecture |
|
|
47
|
+
|
|
48
|
+
## Design overview
|
|
49
|
+
|
|
50
|
+
`@webex/http-core` is the single network boundary for the Webex JS SDK. Every other SDK plugin that
|
|
51
|
+
talks to a Webex service does so through the `request` client this package exports from
|
|
52
|
+
`src/index.js`. Its architectural job is to take a loosely-typed options object, run it through an
|
|
53
|
+
ordered chain of caller-supplied interceptors, hand it to whichever transport is correct for the
|
|
54
|
+
current platform, and run the result back through the same chain in reverse.
|
|
55
|
+
|
|
56
|
+
Three decisions shape everything else:
|
|
57
|
+
|
|
58
|
+
**The public API deliberately mirrors the `request` npm library.** `src/request/request.js` passes
|
|
59
|
+
its options object to that library largely unchanged, which is why option names such as `qs`, `jar`,
|
|
60
|
+
`auth`, `form`, and `formData` appear on the public surface. The browser transport in
|
|
61
|
+
`src/request/request.shim.js` then has to reproduce that same option vocabulary on top of
|
|
62
|
+
`XMLHttpRequest` by hand — `setAuth`, `setCookies`, `setQs`, and `setPayload` exist to translate it.
|
|
63
|
+
This keeps one API across platforms at the cost of a translation layer that must be kept in sync.
|
|
64
|
+
|
|
65
|
+
**Client configuration is built by currying, not by class construction.** `src/index.js` curries
|
|
66
|
+
`protorequest` so that `defaults(options)` returns a new client with those options baked in, and the
|
|
67
|
+
package's own `request` export is simply `protorequest` pre-applied with `json: true` and a default
|
|
68
|
+
`HttpStatusInterceptor`. A consumer layering its own defaults gets a plain function, not an object
|
|
69
|
+
to configure.
|
|
70
|
+
|
|
71
|
+
**Failures are normalized into responses before they are turned into errors.** Neither transport
|
|
72
|
+
rejects on a network failure; both resolve a synthetic response carrying `statusCode: 0`. Rejection
|
|
73
|
+
happens in exactly one place, `src/interceptors/http-status.js`, which selects a typed error class
|
|
74
|
+
from the status code. That keeps every failure — transport-level, CORS, or HTTP status — flowing
|
|
75
|
+
through the same interceptor path, so an interceptor's `onResponseError` handler sees all of them.
|
|
76
|
+
|
|
77
|
+
## Resource inventory and responsibilities
|
|
78
|
+
|
|
79
|
+
| Resource | Kind | Responsibility | Owner | Source | Detailed specification |
|
|
80
|
+
| ------------- | ------- | -------------------------------------------------------------------------------------------------- | ---------------------------- | ----------------- | --------------------------- |
|
|
81
|
+
| `src` | Module | The package surface: client construction, the interceptor extension contract, the HTTP error taxonomy, progress payloads, and MIME detection | Cisco Webex for Developers | `src/index.js` | `src/docs/README.md` |
|
|
82
|
+
| `src/request` | Module | Request execution: applies interceptors around a platform-specific transport and emits progress | Cisco Webex for Developers | `src/request/index.js` | `src/request/docs/README.md` |
|
|
83
|
+
|
|
84
|
+
Ownership is recorded from `README.md`, which names Cisco Webex for Developers as the maintainer.
|
|
85
|
+
|
|
86
|
+
## Interaction and execution flows
|
|
87
|
+
|
|
88
|
+
```mermaid
|
|
89
|
+
flowchart LR
|
|
90
|
+
Caller[SDK plugin] -->|options| Entry["src/index.js<br/>protorequest"]
|
|
91
|
+
Entry -->|defaults applied| Pipeline["src/request/index.js"]
|
|
92
|
+
Pipeline -->|onRequest chain| Utils["src/request/utils.ts<br/>intercept"]
|
|
93
|
+
Utils --> Transport{platform}
|
|
94
|
+
Transport -->|node| Node["src/request/request.js"]
|
|
95
|
+
Transport -->|browser| Shim["src/request/request.shim.js"]
|
|
96
|
+
Node --> Response[response object]
|
|
97
|
+
Shim --> Response
|
|
98
|
+
Response -->|onResponse chain, reversed| Status["src/interceptors/http-status.js"]
|
|
99
|
+
Status -->|status < 400| Caller
|
|
100
|
+
Status -->|status >= 400 or 0| Error["typed HttpError subtype"]
|
|
101
|
+
Error --> Caller
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| From | To | Interaction or transport | Purpose | Failure or compatibility behavior |
|
|
105
|
+
| --------------------------------- | --------------------------------- | ------------------------ | -------------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
106
|
+
| SDK plugin | `src/index.js` | Function call | Obtain a configured client or issue a request | Caller-supplied `options.logger` falls back to `this.logger`, then `console` |
|
|
107
|
+
| `src/index.js` | `src/request/index.js` | Import | Execute the request after defaults are merged | Propagates the returned promise unchanged |
|
|
108
|
+
| `src/request/index.js` | `src/request/utils.ts` | Function call | Fold the interceptor chain over the options and the response | An interceptor rejection short-circuits to the next `onRequestError` handler |
|
|
109
|
+
| `src/request/index.js` | `src/request/request.js` or `.shim.js` | Import (build-time swap) | Perform the actual network I/O | Network failure resolves `statusCode: 0` rather than rejecting |
|
|
110
|
+
| `src/request/index.js` | `options.request` | Caller-supplied function | Let a consumer substitute its own transport entirely | Bypasses both built-in transports; the interceptor chain still runs |
|
|
111
|
+
| Transports | `options.download` / `options.upload` | EventEmitter `progress` | Report byte progress to the caller | Emitters are created per request and discarded with it |
|
|
112
|
+
| `src/interceptors/http-status.js` | Caller | Promise rejection | Convert a failing status into a typed error | Two 404 redirect bodies resolve as successes instead |
|
|
113
|
+
|
|
114
|
+
## Dependency topology
|
|
115
|
+
|
|
116
|
+
| Dependency | Type | Used by | Purpose | Version, failure, or fallback policy |
|
|
117
|
+
| ------------------ | -------- | ------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
118
|
+
| `@webex/common` | Internal | `src`, `src/request` | `Exception` base class for `HttpError`; `isBuffer` predicate | `workspace:*` in `package.json` — versioned with the workspace |
|
|
119
|
+
| `request` | External | `src/request` | The Node transport | `^2.88.0` in `package.json`; an unmaintained library, which constrains upgrades |
|
|
120
|
+
| `file-type` | External | `src` | MIME detection from a buffer in `src/lib/detect.js` | `^16.0.1` in `package.json` |
|
|
121
|
+
| `lodash` | External | `src`, `src/request` | Option merging, currying, and picking | `^4.17.21` in `package.json` |
|
|
122
|
+
| `qs` | External | `src/request` | Query-string and form-body serialization in the browser shim | `^6.7.3` in `package.json` |
|
|
123
|
+
| `safe-buffer` | External | `src/request` | Buffer reconstruction in the Node transport | `^5.2.0` in `package.json` |
|
|
124
|
+
| `global`, `is-function`, `parse-headers`, `xtend` | External | `src` | Runtime dependencies of the vendored XHR fork | Pinned in `package.json`; upgrading them means re-checking `src/lib/xhr.js` |
|
|
125
|
+
|
|
126
|
+
No dependency cycles exist between the two modules: `src/request` is imported by `src`, and never the
|
|
127
|
+
reverse. There is one ordering constraint worth recording — `src/index.js` constructs a default
|
|
128
|
+
`HttpStatusInterceptor` at module load, so importing the package instantiates that interceptor.
|
|
129
|
+
|
|
130
|
+
## Public and consumer surfaces
|
|
131
|
+
|
|
132
|
+
| Surface | Type | Owner | Consumers | Compatibility policy | Source |
|
|
133
|
+
| -------------------------------- | ----- | ------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------- |
|
|
134
|
+
| `http-core-sdk` | SDK | `src` | `@webex/webex-core`, `@webex/internal-plugin-device`, `@webex/internal-plugin-encryption`, `@webex/internal-plugin-scheduler`, `@webex/test-users`, `@webex/helper-image` | Published npm surface; export removal or error-subtype renaming is breaking | `package.json` |
|
|
135
|
+
| `http-core-progress-events` | Event | `src` | Any caller that subscribes to `options.download` / `options.upload` | Payload shape (`loaded`, `total`, `lengthComputable`) is a published contract | `src/progress-event.js` |
|
|
136
|
+
| `http-core-request-transport` | SDK | `src/request` | `src` only | Internal; not exported from the package entry point | `src/request/index.js` |
|
|
137
|
+
| `http-core-xhr-fork` | SDK | `src` | `src/request` browser transport only | Internal; deliberately held close to its upstream original | `src/lib/xhr.js` |
|
|
138
|
+
|
|
139
|
+
Exact export names and signatures stay in the native source declared by `package.json`; the owning
|
|
140
|
+
module specification at `src/docs/README.md` summarizes them per export.
|
|
141
|
+
|
|
142
|
+
## Cross-cutting architecture
|
|
143
|
+
|
|
144
|
+
### Security
|
|
145
|
+
|
|
146
|
+
- Trust boundaries and identity flow: the package is the point where caller credentials become wire
|
|
147
|
+
headers. `src/request/request.shim.js` builds `Authorization: Bearer …` from `options.auth.bearer`
|
|
148
|
+
and `Authorization: Basic …` via `btoa()` from `options.auth.user`/`options.auth.pass`. The Node
|
|
149
|
+
transport delegates the equivalent handling to the `request` library.
|
|
150
|
+
- Sensitive surfaces and data classes: bearer tokens and basic credentials pass through
|
|
151
|
+
`options.auth`; cookies are controlled by `options.jar`, which the browser shim translates into
|
|
152
|
+
`withCredentials`. `src/index.js` marks `download`, `interceptors`, `logger`, and `upload`
|
|
153
|
+
non-enumerable specifically so they do not land in logs.
|
|
154
|
+
- Encryption and secret boundaries: transport security is delegated to the platform (TLS via the
|
|
155
|
+
underlying `request` library or `XMLHttpRequest`). The package stores no secrets and has no
|
|
156
|
+
key material of its own.
|
|
157
|
+
|
|
158
|
+
### Observability and operations
|
|
159
|
+
|
|
160
|
+
- Logging and correlation: every request carries an injected `options.logger`, defaulted in
|
|
161
|
+
`src/index.js` to `this.logger` and then to `console`. Correlation identifiers such as tracking ids
|
|
162
|
+
are contributed by interceptors owned by consuming packages, not by this package.
|
|
163
|
+
- Metrics, traces, and audit signals: none are emitted by this package. Upload and download progress
|
|
164
|
+
is surfaced as caller-facing events rather than as metrics.
|
|
165
|
+
- Ownership and operational entry points: `README.md` names Cisco Webex for Developers as maintainer.
|
|
166
|
+
There is no dashboard, alert, or runbook owned inside this package.
|
|
167
|
+
|
|
168
|
+
### Quality attributes
|
|
169
|
+
|
|
170
|
+
This is a published SDK dependency, so its quality boundary is compatibility and footprint rather
|
|
171
|
+
than availability:
|
|
172
|
+
|
|
173
|
+
- **Cross-platform behavioral parity.** The Node and browser transports must produce the same
|
|
174
|
+
observable result for the same options. This is the package's primary quality constraint and the
|
|
175
|
+
one most easily broken; see the platform matrix below.
|
|
176
|
+
- **Error-type stability.** Consumers branch on subtype identity from `src/http-error-subtypes.js`.
|
|
177
|
+
The taxonomy is a compatibility surface, not an implementation detail.
|
|
178
|
+
- **Node floor.** `package.json` declares `engines.node >= 18`.
|
|
179
|
+
- No coverage or performance threshold is enforced for this package; the repository owner confirmed
|
|
180
|
+
no coverage gate applies.
|
|
181
|
+
|
|
182
|
+
<!-- Include if: repository resources call, import, or exchange events with one another. [condition-id: repo.components_interact] -->
|
|
183
|
+
|
|
184
|
+
## Dependency and interaction topology
|
|
185
|
+
|
|
186
|
+
The interceptor chain is the interaction that cannot be understood from the request flow alone,
|
|
187
|
+
because it runs twice per request in opposite directions.
|
|
188
|
+
|
|
189
|
+
```mermaid
|
|
190
|
+
flowchart LR
|
|
191
|
+
Options[options.interceptors] -->|forward order| OnRequest["onRequest / onRequestError"]
|
|
192
|
+
OnRequest --> Transport[transport]
|
|
193
|
+
Transport --> Reversed["interceptors.slice().reverse()"]
|
|
194
|
+
Reversed -->|reverse order| OnResponse["onResponse / onResponseError"]
|
|
195
|
+
OnResponse --> Caller[caller]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
| From | To | Kind | Purpose | Ordering or failure boundary |
|
|
199
|
+
| ---------------------- | --------------------------------- | ------ | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
200
|
+
| `src/request/index.js` | `src/request/utils.ts` | Call | Apply `onRequest` handlers before dispatch | Forward array order; a rejection routes to the next interceptor's `onRequestError` |
|
|
201
|
+
| `src/request/index.js` | `src/request/utils.ts` | Call | Apply `onResponse` handlers after dispatch | Reverse array order, so the outermost interceptor sees the response last |
|
|
202
|
+
| Transports | `options.download` / `options.upload` | Event | Report progress | Emitted during the request; no ordering guarantee relative to the response promise |
|
|
203
|
+
| `src` | `src/request` | Import | Execute requests | One direction only — `src/request` never imports the package entry point |
|
|
204
|
+
|
|
205
|
+
<!-- Include if: the repository has logging, metrics, tracing, or audit conventions worth standardizing. [condition-id: repo.observability_convention] -->
|
|
206
|
+
|
|
207
|
+
## Observability patterns
|
|
208
|
+
|
|
209
|
+
| Signal | Convention or required fields | Propagation or naming rule | Primary evidence |
|
|
210
|
+
| ------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | -------------------------------- |
|
|
211
|
+
| Logs | An injected `logger` is required on every request; interceptor option dumps are gated behind `ENABLE_VERBOSE_NETWORK_LOGGING` | `options.logger`, falling back to `this.logger` then `console` | `src/lib/interceptor.js`, `src/index.js` |
|
|
212
|
+
| Logs | Browser transport logs request start at `debug`, a `>= 400` result at `warn`, and a successful result at `debug` | Message text embeds method and URI | `src/request/request.shim.js` |
|
|
213
|
+
| Logs | Node transport logs transport errors at `warn` before normalizing them into a `statusCode: 0` response | — | `src/request/request.js` |
|
|
214
|
+
| Metrics | None emitted by this package | N/A | `src/` |
|
|
215
|
+
| Traces | None emitted by this package; correlation headers are added by consumer-owned interceptors | N/A | `src/request/utils.ts` |
|
|
216
|
+
| Audit | None owned by this package | N/A | `src/` |
|
|
217
|
+
|
|
218
|
+
Verbose logging prints the full options object. Because `src/index.js` makes `logger`,
|
|
219
|
+
`interceptors`, `download`, and `upload` non-enumerable, those are excluded — but request bodies and
|
|
220
|
+
headers are not, so the flag must stay off outside debugging.
|
|
221
|
+
|
|
222
|
+
<!-- Include if: modules inherit a shared or base library stack. [condition-id: repo.shared_base_libs] -->
|
|
223
|
+
|
|
224
|
+
## Shared and base libraries
|
|
225
|
+
|
|
226
|
+
| Library | Inherited responsibility | Consumers | Version floor | Compatibility rule |
|
|
227
|
+
| ------------------------------ | ------------------------------------------------------------------ | -------------- | ------------------ | ------------------------------------------------------------------------ |
|
|
228
|
+
| `@webex/eslint-config-legacy` | Lint rules; re-exported wholesale by `.eslintrc.js` with `root: true` | Both modules | `workspace:*` | Rule changes land workspace-wide; local `eslint-disable` marks intentional exceptions |
|
|
229
|
+
| `@webex/babel-config-legacy` | Transpilation config; re-exported by `babel.config.js` | Both modules | `workspace:*` | Determines the syntax the package may use, including class fields in `src/http-error.js` |
|
|
230
|
+
| `@webex/jest-config-legacy` | Unit test config; re-exported by `jest.config.js` | Both modules | `workspace:*` | Sets `testMatch` to `test/unit/**`, so unit specs must live there to run |
|
|
231
|
+
| `@webex/legacy-tools` | The `webex-legacy-tools` build and test runner used by every script | Both modules | `workspace:*` | Owns the `--targets` convention and the `dist/` output layout |
|
|
232
|
+
| `@webex/common` | `Exception` base class and the `isBuffer` predicate | Both modules | `workspace:*` | `HttpError` inherits its serialization behavior from `Exception` |
|
|
233
|
+
|
|
234
|
+
All four configuration packages are consumed by re-export, not by copying — each local config file is
|
|
235
|
+
a two-line passthrough. Change them upstream, not here.
|
|
236
|
+
|
|
237
|
+
<!-- Include if: the repository targets multiple runtime or host platforms. [condition-id: repo.multi_platform] -->
|
|
238
|
+
|
|
239
|
+
## Platform matrix
|
|
240
|
+
|
|
241
|
+
| Platform | Shared versus platform-specific boundary | Entry or build | Support and compatibility constraints |
|
|
242
|
+
| -------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
243
|
+
| Node | Everything except the transport is shared. The Node transport wraps the `request` library. | `src/request/request.js`; default resolution of `main` in `package.json` | `engines.node >= 18`. Buffer bodies get a detected `content-type`; `options.jar` becomes cookie-jar handling |
|
|
244
|
+
| Browser | Same shared pipeline; the transport is replaced at build time and re-implements the option vocabulary over `XMLHttpRequest` | `src/request/request.shim.js`, selected by the `browser` field in `package.json` | `options.jar` becomes `withCredentials`; CORS is enabled by default; upload progress is bound only for PATCH, POST, and PUT |
|
|
245
|
+
|
|
246
|
+
The swap is declared in packaging, not chosen at runtime: `package.json` maps both
|
|
247
|
+
`./dist/request/request.js` and `./src/request/request.js` to their `.shim.js` counterparts. A
|
|
248
|
+
bundler honoring the `browser` field therefore never includes the Node transport. `process` at the
|
|
249
|
+
package root exports `{browser: true}` for bundlers that inline it.
|
|
250
|
+
|
|
251
|
+
Because the boundary is a file swap rather than a runtime branch, the two transports can diverge
|
|
252
|
+
without any test failing on the platform you happen to be running. Changes to one must be mirrored.
|
|
253
|
+
|
|
254
|
+
<!-- Include if: the repository publishes a package or consumer artifact. [condition-id: repo.published_package] -->
|
|
255
|
+
|
|
256
|
+
## Release and versioning
|
|
257
|
+
|
|
258
|
+
| Artifact | Publish target | Versioning rule | Deprecation window | Changelog or migration obligation |
|
|
259
|
+
| ------------------ | -------------- | ------------------------------------------------------- | ------------------ | ----------------------------------------------------------------------- |
|
|
260
|
+
| `@webex/http-core` | npm, via `yarn workspace @webex/http-core deploy:npm` (`package.json`) | Versioned with the surrounding SDK workspace release process | Not defined within this package | Changelog is owned at the workspace root, not per package |
|
|
261
|
+
|
|
262
|
+
The published entry point is `dist/index.js` (`main`), built by `build:src`. `devMain` points at
|
|
263
|
+
`src/index.js` for in-workspace development. Removing an export, renaming an `HttpError` subtype, or
|
|
264
|
+
changing the `ProgressEvent` payload shape are the breaking changes consumers would notice first.
|
|
265
|
+
|
|
266
|
+
<!-- Include if: the repository exposes commands, generators, or stable file outputs. [condition-id: repo.exposes_commands_or_artifacts] -->
|
|
267
|
+
|
|
268
|
+
## Commands and generated artifacts
|
|
269
|
+
|
|
270
|
+
The package declares no `bin`, so it contributes no CLI. What it does expose is a script set in
|
|
271
|
+
`package.json`, addressed through the yarn workspace form naming `@webex/http-core`, and one
|
|
272
|
+
generated file tree.
|
|
273
|
+
|
|
274
|
+
| Command or artifact | Owner | Inputs | Output or side effect | Compatibility boundary |
|
|
275
|
+
| ------------------- | -------------- | ------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
|
|
276
|
+
| `build:src` | `package.json` | `src` | Runs `webex-legacy-tools build` and writes `dist` as JavaScript plus source maps | The only producer of the published artifact. `build` is a thin alias for it and runs no tests |
|
|
277
|
+
| `test:unit` | `package.json` | `test/unit/spec` | Jest run | Self-contained; needs no external dependency |
|
|
278
|
+
| `test:integration` | `package.json` | `test/integration/spec` | Mocha run | Needs a local fixture server and provisioned Webex test users |
|
|
279
|
+
| `test:browser` | `package.json` | `test/integration/spec` | Karma run in a browser | The only tier that exercises `src/request/request.shim.js` and `src/lib/xhr.js` |
|
|
280
|
+
| `test:style` | `package.json` | `src` | eslint run | `src/lib/xhr.js` is exempt by a whole-file disable |
|
|
281
|
+
| `test` | `package.json` | the four tiers above | Chains style, unit, integration, and browser | Builds nothing first, so it exercises `src` and never `dist` |
|
|
282
|
+
| `deploy:npm` | `package.json` | `dist`, `package.json` | `yarn npm publish` to the registry in `publishConfig` | Publishes `dist/index.js` as `main`; see [Release and versioning](#release-and-versioning) |
|
|
283
|
+
| `dist` | `build:src` | `src` | Build output referenced by `main` and by the `browser` field | Generated and not committed; never edit by hand |
|
|
284
|
+
|
|
285
|
+
No committed command runs the build and its tests together: `build` delegates to `build:src`, and
|
|
286
|
+
`test` chains the four tiers without building.
|
|
287
|
+
|
|
288
|
+
<!-- Include if: trust boundaries or identity flows warrant a dedicated architectural view. [condition-id: repo.security_arch_warranted] -->
|
|
289
|
+
|
|
290
|
+
## Security architecture
|
|
291
|
+
|
|
292
|
+
This package is the last place a caller's credentials exist as SDK data and the first place they
|
|
293
|
+
exist as wire format. It makes no authorization decisions of its own: it serializes whatever the
|
|
294
|
+
caller supplies.
|
|
295
|
+
|
|
296
|
+
```mermaid
|
|
297
|
+
flowchart LR
|
|
298
|
+
Caller[SDK plugin] -->|options.auth, options.jar| Entry["src/index.js"]
|
|
299
|
+
Entry --> Interceptors["consumer interceptors<br/>src/request/utils.ts"]
|
|
300
|
+
Interceptors -->|may add auth headers| Transport[transport]
|
|
301
|
+
Transport -->|Authorization header| Service[Webex service]
|
|
302
|
+
Transport -->|withCredentials / cookie jar| Service
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
| Boundary | Control | Evidence |
|
|
306
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
|
307
|
+
| Credential to header | `options.auth.bearer` becomes a `Bearer` header; user/pass becomes a base64 `Basic` header | `src/request/request.shim.js` |
|
|
308
|
+
| Cookie transmission | `options.jar` enables cookie handling; in the browser it sets `withCredentials`, which otherwise defaults to `false` even though CORS defaults to `true` | `src/request/request.js`, `src/request/request.shim.js` |
|
|
309
|
+
| Credential leakage into logs | `logger`, `interceptors`, `download`, and `upload` are made non-enumerable before logging | `src/index.js` |
|
|
310
|
+
| Verbose logging | Full option dumps are gated behind `ENABLE_VERBOSE_NETWORK_LOGGING` and off by default | `src/lib/interceptor.js` |
|
|
311
|
+
| Token acquisition | Out of scope — owned by the consuming authorization plugins, which inject headers through interceptors | `src/request/utils.ts` |
|
|
312
|
+
|
|
313
|
+
No security policy document is owned by this package; see the workspace root for repository-wide
|
|
314
|
+
governance.
|
|
315
|
+
|
|
316
|
+
## Domain language
|
|
317
|
+
|
|
318
|
+
| Term | Repository-specific meaning | Authoritative source |
|
|
319
|
+
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
|
|
320
|
+
| Interceptor | An object with any of `onRequest`, `onRequestError`, `onResponse`, `onResponseError`, folded over each request in both directions | `src/lib/interceptor.js` |
|
|
321
|
+
| Transport | The platform-specific function that performs network I/O; one of two files selected by the `browser` field | `src/request/request.js` |
|
|
322
|
+
| `options` | The single mutable object carrying request configuration, injected services, and per-request emitters through the whole pipeline | `src/request/index.js` |
|
|
323
|
+
| `statusCode: 0` | Not an HTTP status — the package's normalized representation of a transport, network, or CORS failure | `src/http-error-subtypes.js` |
|
|
324
|
+
| Subtype | An `HttpError` descendant selected by status code; `select()` falls back to the category default such as `400` for an unmapped `4xx` | `src/http-error-subtypes.js` |
|
|
325
|
+
| `defaults()` | A curried client factory, not an options object — calling it returns a new request function | `src/index.js` |
|
|
326
|
+
| Prepared options | Options run through the request-interceptor chain and shaped for `fetch`, without being sent | `src/request/utils.ts` |
|
|
327
|
+
|
|
328
|
+
## References and maintenance
|
|
329
|
+
|
|
330
|
+
- Decisions: [adr/](adr/)
|
|
331
|
+
- Instantiated specifications and routing: [specs/README.md](specs/README.md)
|
|
332
|
+
- Repository rules and patterns: [AGENTS.md](../AGENTS.md)
|
|
333
|
+
- Update this document in the same change that alters repository boundaries,
|
|
334
|
+
resource ownership, cross-resource interaction, or cross-cutting
|
|
335
|
+
architecture.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Getting Started
|
|
3
|
+
title: Getting started
|
|
4
|
+
description: Local setup, build, run, and test routing for @webex/http-core.
|
|
5
|
+
tags: [onboarding]
|
|
6
|
+
---
|
|
7
|
+
<!-- sdd-generated-metadata
|
|
8
|
+
doc_kind: standing-doc
|
|
9
|
+
generated_from: getting-started@0.3.0
|
|
10
|
+
generated_by: claude-code
|
|
11
|
+
approved_by: pending
|
|
12
|
+
updated_at: 2026-09-23T06:29:48Z
|
|
13
|
+
validation_status: pass-with-warnings
|
|
14
|
+
-->
|
|
15
|
+
|
|
16
|
+
# Getting started
|
|
17
|
+
|
|
18
|
+
Onboarding for **@webex/http-core**. This package is one workspace member of the `webex-js-sdk`
|
|
19
|
+
monorepo, so dependencies are installed once at the workspace root and every package command is
|
|
20
|
+
addressed through `yarn workspace`.
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
| Tool or access | Version or requirement |
|
|
25
|
+
| ---------------- | ------------------------------------------------------------------------- |
|
|
26
|
+
| Node.js | `>=18` (`package.json` engines) |
|
|
27
|
+
| Yarn | Yarn Berry workspaces; this package is resolved via `workspace:*` dependencies in `package.json` |
|
|
28
|
+
| Webex test users | Required for the integration tier only, via `@webex/test-helper-test-users` (`package.json`) |
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
yarn install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Run it from the workspace root, not from this package directory — the lockfile and the
|
|
37
|
+
`workspace:*` dependencies this package declares in `package.json` are resolved there.
|
|
38
|
+
|
|
39
|
+
## Build
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
yarn workspace @webex/http-core build:src
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This transpiles `src/` into `dist/` with sourcemaps, via `webex-legacy-tools build` as declared in
|
|
46
|
+
`package.json`. The `build` script is an alias that simply calls `build:src`.
|
|
47
|
+
|
|
48
|
+
## Run
|
|
49
|
+
|
|
50
|
+
Not applicable. This package is a library consumed by other SDK packages; it has no runnable entry
|
|
51
|
+
point of its own. `package.json` points `main` at `dist/index.js` and `devMain` at `src/index.js`.
|
|
52
|
+
|
|
53
|
+
## Tests
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
yarn workspace @webex/http-core test:unit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Tier | Command | Test location | Framework | External dependencies |
|
|
60
|
+
| ----------------- | ---------------------------------------------------- | ------------------ | --------- | ----------------------------------------------------------------- |
|
|
61
|
+
| Unit | `yarn workspace @webex/http-core test:unit` | `test/unit` | Jest | None |
|
|
62
|
+
| Integration | `yarn workspace @webex/http-core test:integration` | `test/integration` | Mocha | Local fixture HTTP server (`@webex/test-helper-make-local-url`) and provisioned Webex test users (`@webex/test-helper-test-users`) |
|
|
63
|
+
| Browser | `yarn workspace @webex/http-core test:browser` | `test/integration` | Karma | A browser launcher; runs the same integration specs against the browser transport |
|
|
64
|
+
|
|
65
|
+
`yarn workspace @webex/http-core test` chains style, unit, integration, and browser in that order.
|
|
66
|
+
|
|
67
|
+
To run a single unit spec, pass a path relative to `test/unit/spec/`:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
yarn workspace @webex/http-core test:unit --targets request/utils.js
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- Coverage or quality gate: N/A — this package enforces no coverage threshold. The shared Jest
|
|
74
|
+
configuration it inherits sets `collectCoverage: false` and declares no `coverageThreshold`, and
|
|
75
|
+
the repository owner confirmed no external gate applies to this package.
|
|
76
|
+
- Enforcement source: `jest.config.js` (re-exports the shared `@webex/jest-config-legacy` config)
|
|
77
|
+
- Test environment or QA dependencies: the integration and browser tiers need network access and
|
|
78
|
+
provisioned test users; the unit tier is self-contained.
|
|
79
|
+
|
|
80
|
+
## Configuration and secrets
|
|
81
|
+
|
|
82
|
+
- Required configuration: none for the unit tier.
|
|
83
|
+
- Optional runtime flag: `ENABLE_VERBOSE_NETWORK_LOGGING` turns on per-interceptor request logging
|
|
84
|
+
in `src/lib/interceptor.js`. Leave it unset unless you are debugging; it logs full request options.
|
|
85
|
+
- Secret source: integration test users are provisioned by `@webex/test-helper-test-users`; no
|
|
86
|
+
credentials belong in this package.
|
|
87
|
+
- Package or artifact access: publishing uses `yarn workspace @webex/http-core deploy:npm`.
|
|
88
|
+
- Required neighboring repositories or workspace layout: this package must be built inside the
|
|
89
|
+
`webex-js-sdk` workspace; it depends on `@webex/common` via `workspace:*` in `package.json`.
|
|
90
|
+
- Platform, simulator, device, or SDK setup: the browser tier requires a browser launcher for Karma.
|
|
91
|
+
- Never commit credentials or copy production secrets into a local config.
|
|
92
|
+
|
|
93
|
+
## First-run verification
|
|
94
|
+
|
|
95
|
+
1. Run `yarn workspace @webex/http-core build:src`.
|
|
96
|
+
2. Check that `dist/index.js` exists and that no transpile errors were reported.
|
|
97
|
+
3. Run `yarn workspace @webex/http-core test:unit`.
|
|
98
|
+
|
|
99
|
+
Expected result: the build writes `dist/`, and the unit suite passes across
|
|
100
|
+
`test/unit/spec/index.js`, `test/unit/spec/interceptors/http-status.js`,
|
|
101
|
+
`test/unit/spec/request/index.js`, `test/unit/spec/request/request.shim.js`, and
|
|
102
|
+
`test/unit/spec/request/utils.js`.
|
|
103
|
+
|
|
104
|
+
## Next steps
|
|
105
|
+
|
|
106
|
+
- [Repository architecture](architecture.md)
|
|
107
|
+
- [Specification registry](specs/README.md)
|
|
108
|
+
- [Documentation index](index.md)
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
okf_version: '0.1'
|
|
3
|
+
---
|
|
4
|
+
<!-- sdd-generated-metadata
|
|
5
|
+
doc_kind: standing-doc
|
|
6
|
+
generated_from: docs-index@0.3.0
|
|
7
|
+
generated_by: claude-code
|
|
8
|
+
approved_by: pending
|
|
9
|
+
updated_at: 2026-09-23T06:29:48Z
|
|
10
|
+
validation_status: pass-with-warnings
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
# @webex/http-core documentation
|
|
14
|
+
|
|
15
|
+
Doc map for developers and agents working on the core HTTP client of the Webex JS SDK.
|
|
16
|
+
|
|
17
|
+
## Start here
|
|
18
|
+
|
|
19
|
+
- [Getting started](getting-started.md)
|
|
20
|
+
- [Repository architecture](architecture.md)
|
|
21
|
+
|
|
22
|
+
No service specification exists: this package is a published library, not a deployable service. No
|
|
23
|
+
API specification exists either — it is an HTTP *client* and serves no routes, so its published
|
|
24
|
+
contract is the npm package export surface declared by `package.json`.
|
|
25
|
+
|
|
26
|
+
## Decisions
|
|
27
|
+
|
|
28
|
+
- [adr/](adr/) — architectural decision records
|
|
29
|
+
|
|
30
|
+
## Specifications and contracts
|
|
31
|
+
|
|
32
|
+
- [architecture.md](architecture.md) — canonical repository-wide architecture
|
|
33
|
+
- [specs/README.md](specs/README.md) — manifest-backed module and contract registry
|
|
34
|
+
- `<module-path>/docs/README.md` — the owning specification beside each module's code:
|
|
35
|
+
- [src/docs/README.md](../src/docs/README.md) — the package surface: exports, error taxonomy, interceptor contract
|
|
36
|
+
- [src/request/docs/README.md](../src/request/docs/README.md) — the request pipeline and its Node and browser transports
|
|
37
|
+
- [adr/](adr/) — concrete architectural decisions; blank ADR templates remain under `.sdd/`
|
|
38
|
+
|
|
39
|
+
Use the manifest-linked native source for exact contract details. For this package that is
|
|
40
|
+
`package.json` and the exports it declares; register and link that source from the architecture index
|
|
41
|
+
and owning module spec instead of copying signatures into Markdown.
|
|
42
|
+
|
|
43
|
+
## Related repository resources
|
|
44
|
+
|
|
45
|
+
- [README.md](../README.md) — the package's published usage documentation on npm
|
|
46
|
+
- [AGENTS.md](../AGENTS.md) — agent working instructions for this package
|