@homeflare/alchemy 0.50.0 → 0.51.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.
Files changed (58) hide show
  1. package/dist/unifi/acl-rule-ordering.d.ts +6 -1
  2. package/dist/unifi/acl-rule-ordering.d.ts.map +1 -1
  3. package/dist/unifi/acl-rule.d.ts +6 -1
  4. package/dist/unifi/acl-rule.d.ts.map +1 -1
  5. package/dist/unifi/dns-policy.d.ts +6 -1
  6. package/dist/unifi/dns-policy.d.ts.map +1 -1
  7. package/dist/unifi/fake-unifi.d.ts +4 -0
  8. package/dist/unifi/fake-unifi.d.ts.map +1 -1
  9. package/dist/unifi/firewall-policy-ordering.d.ts +6 -1
  10. package/dist/unifi/firewall-policy-ordering.d.ts.map +1 -1
  11. package/dist/unifi/firewall-policy.d.ts +6 -1
  12. package/dist/unifi/firewall-policy.d.ts.map +1 -1
  13. package/dist/unifi/firewall-zone.d.ts +6 -1
  14. package/dist/unifi/firewall-zone.d.ts.map +1 -1
  15. package/dist/unifi/index.d.ts +5 -3
  16. package/dist/unifi/index.d.ts.map +1 -1
  17. package/dist/unifi/index.js +339 -86
  18. package/dist/unifi/index.js.map +10 -6
  19. package/dist/unifi/network-scope.d.ts +31 -0
  20. package/dist/unifi/network-scope.d.ts.map +1 -0
  21. package/dist/unifi/network-update.d.ts +44 -0
  22. package/dist/unifi/network-update.d.ts.map +1 -0
  23. package/dist/unifi/network.d.ts +32 -12
  24. package/dist/unifi/network.d.ts.map +1 -1
  25. package/dist/unifi/policy.d.ts +89 -1
  26. package/dist/unifi/policy.d.ts.map +1 -1
  27. package/dist/unifi/resource.d.ts +17 -43
  28. package/dist/unifi/resource.d.ts.map +1 -1
  29. package/dist/unifi/traffic-matching-list.d.ts +6 -1
  30. package/dist/unifi/traffic-matching-list.d.ts.map +1 -1
  31. package/dist/unifi/update-reconcile.d.ts +31 -0
  32. package/dist/unifi/update-reconcile.d.ts.map +1 -0
  33. package/dist/unifi/wifi-broadcast.d.ts +6 -1
  34. package/dist/unifi/wifi-broadcast.d.ts.map +1 -1
  35. package/dist/unifi/wire-guard.d.ts +33 -0
  36. package/dist/unifi/wire-guard.d.ts.map +1 -0
  37. package/docs/unifi-network-write.md +90 -0
  38. package/docs/unifi.md +36 -36
  39. package/package.json +1 -1
  40. package/src/unifi/fake-unifi.ts +15 -2
  41. package/src/unifi/handler-allow-news.test.ts +80 -0
  42. package/src/unifi/index.ts +21 -5
  43. package/src/unifi/network-scope.test.ts +203 -0
  44. package/src/unifi/network-scope.ts +75 -0
  45. package/src/unifi/network-update.test.ts +250 -0
  46. package/src/unifi/network-update.ts +95 -0
  47. package/src/unifi/network.test.ts +27 -1
  48. package/src/unifi/network.ts +56 -12
  49. package/src/unifi/policy.ts +128 -10
  50. package/src/unifi/resource.test.ts +15 -3
  51. package/src/unifi/resource.ts +64 -105
  52. package/src/unifi/update-reconcile.ts +126 -0
  53. package/src/unifi/wire-guard-anchor.test.ts +198 -0
  54. package/src/unifi/wire-guard-round2.test.ts +120 -0
  55. package/src/unifi/wire-guard.test.ts +218 -0
  56. package/src/unifi/wire-guard.ts +192 -0
  57. package/src/unifi/write-op-reference.test.ts +38 -2
  58. package/src/unifi/get-only-guard.test.ts +0 -165
@@ -1,165 +0,0 @@
1
- /**
2
- * `GetOnlyHttpClient` (`resource.ts`, B0a/T12) in isolation — against a bare `HttpClient` service,
3
- * no `CredentialsFromEnv`, no real SDK operation. Proves the guard's own mechanism: a `GET`
4
- * reaches the wrapped transport unchanged, and any other method dies with `UnifiNonGetRequest`
5
- * BEFORE the fake server ever sees it (`fake.seen` stays empty for the refused call).
6
- *
7
- * ⚠️ NOT ROUTED THROUGH `unifiHandlers`/`CredentialsFromEnv` ON PURPOSE — see `fake-unifi.ts`'s
8
- * own warning: `CredentialsFromEnv` resolves `UNIFI_NETWORK_*` through Effect's `Config`, which
9
- * this directory's existing tests all avoid depending on for the same reason. Since the guard
10
- * only touches the `HttpClient` service, testing it directly here is both simpler and a more
11
- * precise proof of the mechanism than routing real credentials through it would be.
12
- * ⚠️ CORRECTION (2026-09-26, red team): the line this replaces claimed `network.test.ts`/
13
- * `firewall-zone.test.ts` prove `withCredentials` lets a real GET through. They don't —
14
- * both call `unifiOperations(spec)` directly, which bypasses `unifiHandlers`/`withCredentials`
15
- * (and therefore this guard) entirely. Proof: deleting `Effect.provide(GetOnlyHttpClient)` from
16
- * `withCredentials` (`resource.ts`) left all 56 tests green before this file's own
17
- * `describe('GetOnlyHttpClient installed in unifiHandlers', …)` block below existed. THAT block
18
- * is what closes the gap: it drives `unifiHandlers(...).read`/`.reconcile` — the actual exported
19
- * entry points a real deploy calls — through a `ConfigProvider` override (the same pattern
20
- * `opnsense/write-refusal.test.ts` uses for `CredentialsFromEnv`), so it fails if the guard is
21
- * ever removed from `withCredentials` again.
22
- * ★ REUSES `fakeUnifi` (`fake-unifi.ts`), NOT AN AD HOC MOCK. `fakeUnifi`'s wrapper records
23
- * `seen` BEFORE calling `route`, so even a `route` that would throw still proves whether the
24
- * guard let a request through — the assertion is on `seen`, never on catching that throw.
25
- */
26
- import { describe, expect, test } from 'bun:test';
27
- import * as Cause from 'effect/Cause';
28
- import * as ConfigProvider from 'effect/ConfigProvider';
29
- import * as Effect from 'effect/Effect';
30
- import * as Exit from 'effect/Exit';
31
- import * as Layer from 'effect/Layer';
32
- import * as HttpClient from 'effect/http/HttpClient';
33
- import type * as HttpClientError from 'effect/http/HttpClientError';
34
- import * as HttpClientRequest from 'effect/http/HttpClientRequest';
35
- import { FAKE_BASE, FAKE_KEY, fakeUnifi, fakeUnifiLayer } from './fake-unifi.ts';
36
- import {
37
- GetOnlyHttpClient,
38
- UnifiNonGetRequest,
39
- type UnifiSpec,
40
- unifiHandlers,
41
- } from './resource.ts';
42
-
43
- const FAKE_PATH = '/proxy/network/integration/v1/sites/site-1/networks';
44
- const FAKE_URL = `https://unifi.example.com${FAKE_PATH}`;
45
-
46
- /** One request through `GetOnlyHttpClient`, over a fake transport built by `fakeUnifi`. */
47
- const sendGuarded = (method: string, fetchFn: typeof globalThis.fetch) =>
48
- Effect.runPromiseExit(
49
- Effect.gen(function* () {
50
- const client = yield* HttpClient.HttpClient;
51
- return yield* client.execute(HttpClientRequest.make(method as never)(FAKE_URL));
52
- }).pipe(Effect.provide(GetOnlyHttpClient), Effect.provide(fakeUnifiLayer(fetchFn))),
53
- );
54
-
55
- describe('GetOnlyHttpClient', () => {
56
- test('a GET request passes through unchanged and reaches the transport', async () => {
57
- const fake = fakeUnifi(() => Response.json({ ok: true }));
58
-
59
- const exit = await sendGuarded('GET', fake.fetch);
60
-
61
- expect(Exit.isSuccess(exit)).toBe(true);
62
- expect(fake.seen).toEqual([{ method: 'GET', path: FAKE_PATH }]);
63
- });
64
-
65
- test.each(['POST', 'PUT', 'PATCH', 'DELETE'])(
66
- '%s dies with UnifiNonGetRequest and never reaches the transport',
67
- async (method) => {
68
- const fake = fakeUnifi(() => {
69
- throw new Error(`get-only-guard.test.ts: unexpected ${method} reached the fake transport`);
70
- });
71
-
72
- const exit = await sendGuarded(method, fake.fetch);
73
-
74
- expect(Exit.isFailure(exit)).toBe(true);
75
- if (!Exit.isFailure(exit)) return;
76
- expect(Cause.hasDies(exit.cause)).toBe(true);
77
- expect(Cause.hasFails(exit.cause)).toBe(false);
78
- const defect = Cause.squash(exit.cause);
79
- expect(defect).toBeInstanceOf(UnifiNonGetRequest);
80
- expect((defect as UnifiNonGetRequest).method).toBe(method);
81
- // ⛔ THE PROOF: the fake transport never even recorded the call -- the guard refused the
82
- // request in `mapRequestEffect`, before dispatch, not after a failed response.
83
- expect(fake.seen).toEqual([]);
84
- },
85
- );
86
- });
87
-
88
- interface ProbeProps {
89
- id: string;
90
- }
91
-
92
- /**
93
- * A `fetchLive` that sends exactly one raw request over whatever `method` the test wants to
94
- * probe — not a real SDK operation, on purpose: this block proves the GUARD'S INSTALLATION in
95
- * `unifiHandlers`, not any one family's own all-GET behavior (`network.test.ts`/
96
- * `firewall-zone.test.ts` already prove that, for calls that bypass `unifiHandlers` entirely).
97
- */
98
- const probeSpec = (
99
- method: string,
100
- ): UnifiSpec<ProbeProps, ProbeProps, ProbeProps, HttpClientError.HttpClientError> => ({
101
- type: 'Test.Probe',
102
- describe: (props) => `probe/${props.id}`,
103
- fetchLive: (props) =>
104
- Effect.gen(function* () {
105
- const client = yield* HttpClient.HttpClient;
106
- yield* client.execute(HttpClientRequest.make(method as never)(`${FAKE_BASE}/probe`));
107
- return props;
108
- }),
109
- attributes: (live) => live,
110
- matches: () => true,
111
- });
112
-
113
- /**
114
- * Overrides the `ConfigProvider` `CredentialsFromEnv` resolves `UNIFI_NETWORK_*` against — the
115
- * SAME pattern `opnsense/write-refusal.test.ts` uses for its own `CredentialsFromEnv` — WITHOUT
116
- * touching real `process.env` (a parallel test file could race on that). `unifiHandlers`'s
117
- * `withCredentials` bakes in `CredentialsFromEnv` itself, so providing a `Credentials` layer from
118
- * OUTSIDE (the way `fake-unifi.ts`'s own `fakeUnifiLayer` does for tests that call `spec.fetchLive`
119
- * directly) would be shadowed and do nothing here — this ConfigProvider override is what actually
120
- * reaches it.
121
- */
122
- const fakeCredentialsConfigProvider = ConfigProvider.layer(
123
- ConfigProvider.fromUnknown({
124
- UNIFI_NETWORK_API_BASE_URL: FAKE_BASE,
125
- UNIFI_NETWORK_API_KEY: FAKE_KEY,
126
- }),
127
- );
128
-
129
- describe('GetOnlyHttpClient is installed in unifiHandlers (IMPORTANT-1, red team 2026-09-26)', () => {
130
- test('a GET through the real handler entry point still reaches the transport', async () => {
131
- const fake = fakeUnifi(() => Response.json({ id: 'w1' }));
132
- const attrs = await Effect.runPromise(
133
- unifiHandlers(probeSpec('GET'))
134
- .read({ olds: { id: 'w1' }, output: undefined })
135
- .pipe(
136
- Effect.provide(Layer.mergeAll(fakeUnifiLayer(fake.fetch), fakeCredentialsConfigProvider)),
137
- ),
138
- );
139
- expect(attrs).toEqual({ id: 'w1' });
140
- expect(fake.seen).toEqual([{ method: 'GET', path: '/proxy/network/integration/probe' }]);
141
- });
142
-
143
- test('a non-GET through the real handler entry point dies, never reaching the transport', async () => {
144
- const fake = fakeUnifi(() => {
145
- throw new Error('get-only-guard.test.ts: unexpected POST reached the fake transport');
146
- });
147
- const exit = await Effect.runPromiseExit(
148
- unifiHandlers(probeSpec('POST'))
149
- .read({ olds: { id: 'w1' }, output: undefined })
150
- .pipe(
151
- Effect.provide(Layer.mergeAll(fakeUnifiLayer(fake.fetch), fakeCredentialsConfigProvider)),
152
- ),
153
- );
154
- expect(Exit.isFailure(exit)).toBe(true);
155
- if (!Exit.isFailure(exit)) return;
156
- expect(Cause.hasDies(exit.cause)).toBe(true);
157
- expect(Cause.squash(exit.cause)).toBeInstanceOf(UnifiNonGetRequest);
158
- // ⛔ THIS IS THE PROOF THE FILE HEADER PROMISES. Verified by hand (2026-09-26): deleting
159
- // `Effect.provide(GetOnlyHttpClient)` from `withCredentials` (`resource.ts`) turns this
160
- // exact test into a passing `Response.json` round-trip with a non-empty `fake.seen` --
161
- // i.e. it FAILS the instant the guard installation regresses, which no test in this
162
- // directory could do before this block existed (IMPORTANT-1).
163
- expect(fake.seen).toEqual([]);
164
- });
165
- });