@sanctuary-framework/mcp-server 0.10.1 → 0.10.2

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/dist/index.cjs CHANGED
@@ -8703,6 +8703,24 @@ var DashboardApprovalChannel = class {
8703
8703
  rateLimits = /* @__PURE__ */ new Map();
8704
8704
  /** Whether the dashboard is running in standalone mode (no MCP server) */
8705
8705
  _standaloneMode = false;
8706
+ /**
8707
+ * v0.10.2: when set, requests from loopback addresses (127.0.0.1 / ::1)
8708
+ * are treated as authenticated without requiring a Bearer token or
8709
+ * dashboard session cookie. Only the `startStandaloneDashboard` boot
8710
+ * path enables this, and ONLY after the supplied passphrase successfully
8711
+ * decrypts at least one stored identity — proving the caller already
8712
+ * holds the primary secret that protects every piece of Sanctuary state.
8713
+ *
8714
+ * Rationale: the dashboard auth token is a dashboard-access credential
8715
+ * layered on top of the master-key unlock. Once the operator has already
8716
+ * presented the passphrase on the command line (terminal-side auth), a
8717
+ * second login prompt in the auto-opened browser just trains users to
8718
+ * paste secrets into web forms — the exact habit Sanctuary exists to
8719
+ * discourage. Remote (non-loopback) callers still require the bearer
8720
+ * token, so this is a localhost-only ergonomics unlock, not a network
8721
+ * policy change.
8722
+ */
8723
+ _autoAuthLocalhost = false;
8706
8724
  constructor(config) {
8707
8725
  this.config = config;
8708
8726
  this.authToken = config.auth_token;
@@ -8738,6 +8756,26 @@ var DashboardApprovalChannel = class {
8738
8756
  setStandaloneMode(standalone) {
8739
8757
  this._standaloneMode = standalone;
8740
8758
  }
8759
+ /**
8760
+ * v0.10.2: enable (or disable) the loopback auto-auth fast path. See
8761
+ * {@link _autoAuthLocalhost} for the rationale and threat model. Callers
8762
+ * should gate this on both (a) the dashboard host being a loopback
8763
+ * interface and (b) the master-key unlock having succeeded against
8764
+ * on-disk state.
8765
+ */
8766
+ setAutoAuthLocalhost(enabled) {
8767
+ this._autoAuthLocalhost = enabled;
8768
+ }
8769
+ /**
8770
+ * v0.10.2: is this request from a loopback interface? We treat the
8771
+ * standard IPv4/IPv6 loopback addresses plus the IPv4-mapped IPv6 form
8772
+ * as loopback so LAN clients never accidentally hit the unauthenticated
8773
+ * fast path even on hosts where the HTTP server binds 0.0.0.0.
8774
+ */
8775
+ isLoopbackRequest(req) {
8776
+ const addr = this.getRemoteAddr(req);
8777
+ return addr === "127.0.0.1" || addr === "::1" || addr === "localhost";
8778
+ }
8741
8779
  /**
8742
8780
  * Start the HTTP(S) server for the dashboard.
8743
8781
  */
@@ -8887,6 +8925,9 @@ var DashboardApprovalChannel = class {
8887
8925
  */
8888
8926
  checkAuth(req, url, res) {
8889
8927
  if (!this.authToken) return true;
8928
+ if (this._autoAuthLocalhost && this.isLoopbackRequest(req)) {
8929
+ return true;
8930
+ }
8890
8931
  const authHeader = req.headers.authorization;
8891
8932
  if (authHeader) {
8892
8933
  const parts = authHeader.split(" ");
@@ -8912,6 +8953,9 @@ var DashboardApprovalChannel = class {
8912
8953
  */
8913
8954
  isAuthenticated(req, url) {
8914
8955
  if (!this.authToken) return true;
8956
+ if (this._autoAuthLocalhost && this.isLoopbackRequest(req)) {
8957
+ return true;
8958
+ }
8915
8959
  const authHeader = req.headers.authorization;
8916
8960
  if (authHeader) {
8917
8961
  const parts = authHeader.split(" ");