@fonderie/client 0.23.0 → 0.25.0

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.
@@ -226,6 +226,7 @@ new BillingClient(http: HttpClient, tokens: TokenStore): BillingClient
226
226
  interface IConfigAdminClientOptions {
227
227
  baseUrl: string;
228
228
  adminToken: string;
229
+ prefix?: string;
229
230
  actor?: string;
230
231
  }
231
232
 
@@ -262,9 +263,31 @@ new ConfigAdminClient(opts: IConfigAdminClientOptions): ConfigAdminClient
262
263
  .rollbackSecret(key: string, input: IRollbackInput, environment?: string | undefined): Promise<IApiResponse<ISecretEntry>>
263
264
  .revealSecret(key: string, environment?: string | undefined): Promise<IApiResponse<IRevealSecretResult>>
264
265
 
266
+ interface IAdminClientOptions {
267
+ baseUrl: string;
268
+ adminToken: string;
269
+ prefix?: string;
270
+ actor?: string;
271
+ }
272
+
273
+ interface IAdminLogQuery {
274
+ limit?: number;
275
+ before?: string;
276
+ }
277
+
278
+ new AdminClient(opts: IAdminClientOptions): AdminClient
279
+ .attention(): Promise<IApiResponse<IAdminAttention>>
280
+ .manifest(): Promise<IApiResponse<IAdminManifest>>
281
+ .doctor(): Promise<IApiResponse<IAdminDoctorReport>>
282
+ .config(): Promise<IApiResponse<IAdminConfigReport>>
283
+ .routes(): Promise<IApiResponse<IAdminRoutesReport>>
284
+ .tokens(): Promise<IApiResponse<IAdminTokensReport>>
285
+ .adminLog(query?: IAdminLogQuery): Promise<IApiResponse<IAdminLogPage>>
286
+
265
287
  interface ICourierAdminClientOptions {
266
288
  baseUrl: string;
267
289
  adminToken: string;
290
+ prefix?: string;
268
291
  actor?: string;
269
292
  }
270
293
 
@@ -599,6 +622,122 @@ interface ICheckoutUrlResult {
599
622
  url: string;
600
623
  }
601
624
 
625
+ type AdminRouteGuard = 'admin' | 'probe' | 'app';
626
+
627
+ interface IAdminAttention {
628
+ generatedAt: string;
629
+ ok: boolean;
630
+ items: IAdminAttentionItem[];
631
+ }
632
+
633
+ interface IAdminAttentionItem {
634
+ source: string;
635
+ severity: 'error' | 'advice';
636
+ message: string;
637
+ }
638
+
639
+ interface IAdminCheckResult {
640
+ name: string;
641
+ module: string;
642
+ ok: boolean;
643
+ findings: string[];
644
+ skipped?: string;
645
+ durationMs: number;
646
+ }
647
+
648
+ interface IAdminConfigReport {
649
+ generatedAt: string;
650
+ readiness: IAdminReadiness;
651
+ modules: Array<{
652
+ name: string;
653
+ problems: IAdminReadinessProblem[];
654
+ }>;
655
+ env: Array<{
656
+ name: string;
657
+ set: boolean;
658
+ }>;
659
+ }
660
+
661
+ interface IAdminDoctorReport {
662
+ generatedAt: string;
663
+ ok: boolean;
664
+ checks: IAdminCheckResult[];
665
+ }
666
+
667
+ interface IAdminLogEntry {
668
+ id: string;
669
+ at: string;
670
+ actor: string;
671
+ method: string;
672
+ path: string;
673
+ route: string;
674
+ module: string;
675
+ status: number;
676
+ durationMs: number;
677
+ requestId: string | null;
678
+ clientIp: string | null;
679
+ }
680
+
681
+ interface IAdminLogPage {
682
+ entries: IAdminLogEntry[];
683
+ next: string | null;
684
+ }
685
+
686
+ interface IAdminManifest {
687
+ generatedAt: string;
688
+ env: string;
689
+ admin: {
690
+ version: string;
691
+ log: boolean;
692
+ };
693
+ modules: IAdminModuleEntry[];
694
+ readiness: IAdminReadiness;
695
+ routes: IAdminRouteEntry[];
696
+ }
697
+
698
+ interface IAdminModuleEntry {
699
+ name: string;
700
+ version: string | null;
701
+ readiness: IAdminReadiness;
702
+ describesAdmin: boolean;
703
+ }
704
+
705
+ interface IAdminReadiness {
706
+ ok: boolean;
707
+ problems: IAdminReadinessProblem[];
708
+ }
709
+
710
+ interface IAdminReadinessProblem {
711
+ module: string;
712
+ severity: 'error' | 'warning';
713
+ message: string;
714
+ }
715
+
716
+ interface IAdminRouteEntry {
717
+ method: string;
718
+ path: string;
719
+ module?: string;
720
+ }
721
+
722
+ interface IAdminRoutesReport {
723
+ generatedAt: string;
724
+ routes: Array<IAdminRouteEntry & {
725
+ guard: AdminRouteGuard;
726
+ }>;
727
+ }
728
+
729
+ interface IAdminTokensReport {
730
+ generatedAt: string;
731
+ admin: {
732
+ ok: boolean;
733
+ problems: IAdminReadinessProblem[];
734
+ };
735
+ legacy: Array<{
736
+ module: string;
737
+ set: boolean;
738
+ }>;
739
+ }
740
+
602
741
  interface IConfigEntry {
603
742
  key: string;
604
743
  value: unknown;
package/dist/index.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ AdminClient: () => AdminClient,
23
24
  AuditClient: () => AuditClient,
24
25
  AuthClient: () => AuthClient,
25
26
  BillingClient: () => BillingClient,
@@ -1589,180 +1590,281 @@ function envQuery(environment) {
1589
1590
  var ConfigAdminClient = class {
1590
1591
  http;
1591
1592
  adminToken;
1593
+ prefix;
1592
1594
  actorHeaders;
1593
1595
  constructor(opts) {
1594
1596
  this.http = new HttpClient(opts.baseUrl);
1595
1597
  this.adminToken = opts.adminToken;
1598
+ this.prefix = opts.prefix?.replace(/\/+$/, "");
1596
1599
  this.actorHeaders = opts.actor ? { "X-Actor": opts.actor } : void 0;
1597
1600
  }
1601
+ // The path literals stay on the legacy '/admin/...' so the route table and
1602
+ // the coverage gate read them; the prefix is applied here at request time.
1603
+ rebase(opts) {
1604
+ if (!this.prefix) return opts;
1605
+ return { ...opts, path: opts.path.replace(/^\/admin(?=\/|\?|$)/, this.prefix) };
1606
+ }
1598
1607
  // ── Config ───────────────────────────────────────────────────────────────
1599
1608
  listConfig(environment) {
1600
- return this.http.request({
1601
- method: "GET",
1602
- path: `/admin/config${envQuery(environment)}`,
1603
- token: this.adminToken
1604
- });
1609
+ return this.http.request(
1610
+ this.rebase({
1611
+ method: "GET",
1612
+ path: `/admin/config${envQuery(environment)}`,
1613
+ token: this.adminToken
1614
+ })
1615
+ );
1605
1616
  }
1606
1617
  getConfig(key, environment) {
1607
- return this.http.request({
1608
- method: "GET",
1609
- path: `/admin/config/${encodeURIComponent(key)}${envQuery(environment)}`,
1610
- token: this.adminToken
1611
- });
1618
+ return this.http.request(
1619
+ this.rebase({
1620
+ method: "GET",
1621
+ path: `/admin/config/${encodeURIComponent(key)}${envQuery(environment)}`,
1622
+ token: this.adminToken
1623
+ })
1624
+ );
1612
1625
  }
1613
1626
  setConfig(key, input, environment) {
1614
- return this.http.request({
1615
- method: "PUT",
1616
- path: `/admin/config/${encodeURIComponent(key)}${envQuery(environment)}`,
1617
- body: input,
1618
- token: this.adminToken,
1619
- headers: this.actorHeaders
1620
- });
1627
+ return this.http.request(
1628
+ this.rebase({
1629
+ method: "PUT",
1630
+ path: `/admin/config/${encodeURIComponent(key)}${envQuery(environment)}`,
1631
+ body: input,
1632
+ token: this.adminToken,
1633
+ headers: this.actorHeaders
1634
+ })
1635
+ );
1621
1636
  }
1622
1637
  deleteConfig(key, environment) {
1623
- return this.http.request({
1624
- method: "DELETE",
1625
- path: `/admin/config/${encodeURIComponent(key)}${envQuery(environment)}`,
1626
- token: this.adminToken,
1627
- headers: this.actorHeaders
1628
- });
1638
+ return this.http.request(
1639
+ this.rebase({
1640
+ method: "DELETE",
1641
+ path: `/admin/config/${encodeURIComponent(key)}${envQuery(environment)}`,
1642
+ token: this.adminToken,
1643
+ headers: this.actorHeaders
1644
+ })
1645
+ );
1629
1646
  }
1630
1647
  listConfigRevisions(key, environment) {
1631
- return this.http.request({
1632
- method: "GET",
1633
- path: `/admin/config/${encodeURIComponent(key)}/revisions${envQuery(environment)}`,
1634
- token: this.adminToken
1635
- });
1648
+ return this.http.request(
1649
+ this.rebase({
1650
+ method: "GET",
1651
+ path: `/admin/config/${encodeURIComponent(key)}/revisions${envQuery(environment)}`,
1652
+ token: this.adminToken
1653
+ })
1654
+ );
1636
1655
  }
1637
1656
  rollbackConfig(key, input, environment) {
1638
- return this.http.request({
1639
- method: "POST",
1640
- path: `/admin/config/${encodeURIComponent(key)}/rollback${envQuery(environment)}`,
1641
- body: input,
1642
- token: this.adminToken,
1643
- headers: this.actorHeaders
1644
- });
1657
+ return this.http.request(
1658
+ this.rebase({
1659
+ method: "POST",
1660
+ path: `/admin/config/${encodeURIComponent(key)}/rollback${envQuery(environment)}`,
1661
+ body: input,
1662
+ token: this.adminToken,
1663
+ headers: this.actorHeaders
1664
+ })
1665
+ );
1645
1666
  }
1646
1667
  // ── Secrets (masked) ─────────────────────────────────────────────────────
1647
1668
  listSecrets(environment) {
1648
- return this.http.request({
1649
- method: "GET",
1650
- path: `/admin/secrets${envQuery(environment)}`,
1651
- token: this.adminToken
1652
- });
1669
+ return this.http.request(
1670
+ this.rebase({
1671
+ method: "GET",
1672
+ path: `/admin/secrets${envQuery(environment)}`,
1673
+ token: this.adminToken
1674
+ })
1675
+ );
1653
1676
  }
1654
1677
  getSecret(key, environment) {
1655
- return this.http.request({
1656
- method: "GET",
1657
- path: `/admin/secrets/${encodeURIComponent(key)}${envQuery(environment)}`,
1658
- token: this.adminToken
1659
- });
1678
+ return this.http.request(
1679
+ this.rebase({
1680
+ method: "GET",
1681
+ path: `/admin/secrets/${encodeURIComponent(key)}${envQuery(environment)}`,
1682
+ token: this.adminToken
1683
+ })
1684
+ );
1660
1685
  }
1661
1686
  setSecret(key, input, environment) {
1662
- return this.http.request({
1663
- method: "PUT",
1664
- path: `/admin/secrets/${encodeURIComponent(key)}${envQuery(environment)}`,
1665
- body: input,
1666
- token: this.adminToken,
1667
- headers: this.actorHeaders
1668
- });
1687
+ return this.http.request(
1688
+ this.rebase({
1689
+ method: "PUT",
1690
+ path: `/admin/secrets/${encodeURIComponent(key)}${envQuery(environment)}`,
1691
+ body: input,
1692
+ token: this.adminToken,
1693
+ headers: this.actorHeaders
1694
+ })
1695
+ );
1669
1696
  }
1670
1697
  deleteSecret(key, environment) {
1671
- return this.http.request({
1672
- method: "DELETE",
1673
- path: `/admin/secrets/${encodeURIComponent(key)}${envQuery(environment)}`,
1674
- token: this.adminToken,
1675
- headers: this.actorHeaders
1676
- });
1698
+ return this.http.request(
1699
+ this.rebase({
1700
+ method: "DELETE",
1701
+ path: `/admin/secrets/${encodeURIComponent(key)}${envQuery(environment)}`,
1702
+ token: this.adminToken,
1703
+ headers: this.actorHeaders
1704
+ })
1705
+ );
1677
1706
  }
1678
1707
  listSecretRevisions(key, environment) {
1679
- return this.http.request({
1680
- method: "GET",
1681
- path: `/admin/secrets/${encodeURIComponent(key)}/revisions${envQuery(environment)}`,
1682
- token: this.adminToken
1683
- });
1708
+ return this.http.request(
1709
+ this.rebase({
1710
+ method: "GET",
1711
+ path: `/admin/secrets/${encodeURIComponent(key)}/revisions${envQuery(environment)}`,
1712
+ token: this.adminToken
1713
+ })
1714
+ );
1684
1715
  }
1685
1716
  rollbackSecret(key, input, environment) {
1686
- return this.http.request({
1687
- method: "POST",
1688
- path: `/admin/secrets/${encodeURIComponent(key)}/rollback${envQuery(environment)}`,
1689
- body: input,
1690
- token: this.adminToken,
1691
- headers: this.actorHeaders
1692
- });
1717
+ return this.http.request(
1718
+ this.rebase({
1719
+ method: "POST",
1720
+ path: `/admin/secrets/${encodeURIComponent(key)}/rollback${envQuery(environment)}`,
1721
+ body: input,
1722
+ token: this.adminToken,
1723
+ headers: this.actorHeaders
1724
+ })
1725
+ );
1693
1726
  }
1694
1727
  // POST (not GET) so the decrypted value never lands in a URL or access log.
1695
1728
  revealSecret(key, environment) {
1729
+ return this.http.request(
1730
+ this.rebase({
1731
+ method: "POST",
1732
+ path: `/admin/secrets/${encodeURIComponent(key)}/reveal${envQuery(environment)}`,
1733
+ token: this.adminToken,
1734
+ headers: this.actorHeaders
1735
+ })
1736
+ );
1737
+ }
1738
+ };
1739
+
1740
+ // src/modules/admin.ts
1741
+ var AdminClient = class {
1742
+ http;
1743
+ adminToken;
1744
+ prefix;
1745
+ actorHeaders;
1746
+ constructor(opts) {
1747
+ this.http = new HttpClient(opts.baseUrl);
1748
+ this.adminToken = opts.adminToken;
1749
+ this.prefix = (opts.prefix ?? "/_admin").replace(/\/+$/, "");
1750
+ this.actorHeaders = opts.actor ? { "X-Actor": opts.actor } : void 0;
1751
+ }
1752
+ get(suffix) {
1696
1753
  return this.http.request({
1697
- method: "POST",
1698
- path: `/admin/secrets/${encodeURIComponent(key)}/reveal${envQuery(environment)}`,
1754
+ method: "GET",
1755
+ path: `${this.prefix}${suffix}`,
1699
1756
  token: this.adminToken,
1700
1757
  headers: this.actorHeaders
1701
1758
  });
1702
1759
  }
1760
+ attention() {
1761
+ return this.get("");
1762
+ }
1763
+ manifest() {
1764
+ return this.get("/manifest");
1765
+ }
1766
+ doctor() {
1767
+ return this.get("/doctor");
1768
+ }
1769
+ config() {
1770
+ return this.get("/config");
1771
+ }
1772
+ routes() {
1773
+ return this.get("/routes");
1774
+ }
1775
+ tokens() {
1776
+ return this.get("/access/tokens");
1777
+ }
1778
+ adminLog(query = {}) {
1779
+ const q = new URLSearchParams();
1780
+ if (query.limit) q.set("limit", String(query.limit));
1781
+ if (query.before) q.set("before", query.before);
1782
+ const qs = q.toString();
1783
+ return this.get(`/activity/admin-log${qs ? `?${qs}` : ""}`);
1784
+ }
1703
1785
  };
1704
1786
 
1705
1787
  // src/modules/courier-admin.ts
1706
1788
  var CourierAdminClient = class {
1707
1789
  http;
1708
1790
  adminToken;
1791
+ prefix;
1709
1792
  actorHeaders;
1710
1793
  constructor(opts) {
1711
1794
  this.http = new HttpClient(opts.baseUrl);
1712
1795
  this.adminToken = opts.adminToken;
1796
+ this.prefix = opts.prefix?.replace(/\/+$/, "");
1713
1797
  this.actorHeaders = opts.actor ? { "X-Actor": opts.actor } : void 0;
1714
1798
  }
1799
+ // The path literals stay on the legacy '/admin/...' so the route table and
1800
+ // the coverage gate read them; the prefix is applied here at request time.
1801
+ rebase(opts) {
1802
+ if (!this.prefix) return opts;
1803
+ return { ...opts, path: opts.path.replace(/^\/admin(?=\/|\?|$)/, this.prefix) };
1804
+ }
1715
1805
  listTemplates() {
1716
- return this.http.request({
1717
- method: "GET",
1718
- path: "/admin/templates",
1719
- token: this.adminToken
1720
- });
1806
+ return this.http.request(
1807
+ this.rebase({
1808
+ method: "GET",
1809
+ path: "/admin/templates",
1810
+ token: this.adminToken
1811
+ })
1812
+ );
1721
1813
  }
1722
1814
  getTemplate(type, locale) {
1723
1815
  const q = locale ? `?locale=${encodeURIComponent(locale)}` : "";
1724
- return this.http.request({
1725
- method: "GET",
1726
- path: `/admin/templates/${encodeURIComponent(type)}${q}`,
1727
- token: this.adminToken
1728
- });
1816
+ return this.http.request(
1817
+ this.rebase({
1818
+ method: "GET",
1819
+ path: `/admin/templates/${encodeURIComponent(type)}${q}`,
1820
+ token: this.adminToken
1821
+ })
1822
+ );
1729
1823
  }
1730
1824
  setTemplate(type, input, locale) {
1731
1825
  const q = locale ? `?locale=${encodeURIComponent(locale)}` : "";
1732
- return this.http.request({
1733
- method: "PUT",
1734
- path: `/admin/templates/${encodeURIComponent(type)}${q}`,
1735
- body: input,
1736
- token: this.adminToken,
1737
- headers: this.actorHeaders
1738
- });
1826
+ return this.http.request(
1827
+ this.rebase({
1828
+ method: "PUT",
1829
+ path: `/admin/templates/${encodeURIComponent(type)}${q}`,
1830
+ body: input,
1831
+ token: this.adminToken,
1832
+ headers: this.actorHeaders
1833
+ })
1834
+ );
1739
1835
  }
1740
1836
  deleteTemplate(type, locale) {
1741
1837
  const q = locale ? `?locale=${encodeURIComponent(locale)}` : "";
1742
- return this.http.request({
1743
- method: "DELETE",
1744
- path: `/admin/templates/${encodeURIComponent(type)}${q}`,
1745
- token: this.adminToken,
1746
- headers: this.actorHeaders
1747
- });
1838
+ return this.http.request(
1839
+ this.rebase({
1840
+ method: "DELETE",
1841
+ path: `/admin/templates/${encodeURIComponent(type)}${q}`,
1842
+ token: this.adminToken,
1843
+ headers: this.actorHeaders
1844
+ })
1845
+ );
1748
1846
  }
1749
1847
  listRevisions(type, locale) {
1750
1848
  const q = locale ? `?locale=${encodeURIComponent(locale)}` : "";
1751
- return this.http.request({
1752
- method: "GET",
1753
- path: `/admin/templates/${encodeURIComponent(type)}/revisions${q}`,
1754
- token: this.adminToken
1755
- });
1849
+ return this.http.request(
1850
+ this.rebase({
1851
+ method: "GET",
1852
+ path: `/admin/templates/${encodeURIComponent(type)}/revisions${q}`,
1853
+ token: this.adminToken
1854
+ })
1855
+ );
1756
1856
  }
1757
1857
  rollback(type, input, locale) {
1758
1858
  const q = locale ? `?locale=${encodeURIComponent(locale)}` : "";
1759
- return this.http.request({
1760
- method: "POST",
1761
- path: `/admin/templates/${encodeURIComponent(type)}/rollback${q}`,
1762
- body: input,
1763
- token: this.adminToken,
1764
- headers: this.actorHeaders
1765
- });
1859
+ return this.http.request(
1860
+ this.rebase({
1861
+ method: "POST",
1862
+ path: `/admin/templates/${encodeURIComponent(type)}/rollback${q}`,
1863
+ body: input,
1864
+ token: this.adminToken,
1865
+ headers: this.actorHeaders
1866
+ })
1867
+ );
1766
1868
  }
1767
1869
  };
1768
1870
 
@@ -1772,6 +1874,7 @@ function isMfaRequired(result) {
1772
1874
  }
1773
1875
  // Annotate the CommonJS export names for ESM import in node:
1774
1876
  0 && (module.exports = {
1877
+ AdminClient,
1775
1878
  AuditClient,
1776
1879
  AuthClient,
1777
1880
  BillingClient,