straycall 0.1.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.
data/docs/styles.css ADDED
@@ -0,0 +1,718 @@
1
+ :root {
2
+ color-scheme: dark;
3
+ --bg: #07111b;
4
+ --bg-deep: #040b12;
5
+ --surface: #0c1a27;
6
+ --border: #244052;
7
+ --text: #edf8ff;
8
+ --muted: #a9c0ce;
9
+ --primary: #38bdf8;
10
+ --primary-strong: #7dd3fc;
11
+ --accent: #fb923c;
12
+ --danger: #fda4af;
13
+ --max-width: 1180px;
14
+ --sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
15
+ --mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
16
+ }
17
+
18
+ * {
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ html {
23
+ scroll-behavior: smooth;
24
+ }
25
+
26
+ body {
27
+ margin: 0;
28
+ background:
29
+ radial-gradient(circle at 78% 4%, rgb(14 165 233 / 11%), transparent 28rem),
30
+ var(--bg);
31
+ color: var(--text);
32
+ font-family: var(--sans);
33
+ font-size: 16px;
34
+ line-height: 1.65;
35
+ }
36
+
37
+ a {
38
+ color: inherit;
39
+ }
40
+
41
+ a:focus-visible {
42
+ outline: 3px solid var(--accent);
43
+ outline-offset: 4px;
44
+ }
45
+
46
+ .skip-link {
47
+ position: fixed;
48
+ z-index: 100;
49
+ top: 1rem;
50
+ left: 1rem;
51
+ padding: 0.75rem 1rem;
52
+ border-radius: 0.5rem;
53
+ background: var(--text);
54
+ color: var(--bg-deep);
55
+ font-weight: 700;
56
+ transform: translateY(-200%);
57
+ }
58
+
59
+ .skip-link:focus {
60
+ transform: translateY(0);
61
+ }
62
+
63
+ .site-header,
64
+ main,
65
+ footer {
66
+ width: min(calc(100% - 3rem), var(--max-width));
67
+ margin-inline: auto;
68
+ }
69
+
70
+ .site-header {
71
+ display: flex;
72
+ min-height: 5.5rem;
73
+ align-items: center;
74
+ justify-content: space-between;
75
+ gap: 2rem;
76
+ border-bottom: 1px solid var(--border);
77
+ }
78
+
79
+ .brand {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ gap: 0.7rem;
83
+ color: var(--text);
84
+ font-weight: 750;
85
+ letter-spacing: -0.02em;
86
+ text-decoration: none;
87
+ }
88
+
89
+ .brand-mark {
90
+ display: grid;
91
+ width: 2rem;
92
+ height: 2rem;
93
+ place-items: center;
94
+ border: 1px solid rgb(56 189 248 / 45%);
95
+ border-radius: 0.45rem;
96
+ background: rgb(56 189 248 / 10%);
97
+ color: var(--primary-strong);
98
+ font-family: var(--mono);
99
+ font-size: 0.78rem;
100
+ }
101
+
102
+ nav {
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 1.6rem;
106
+ }
107
+
108
+ nav a,
109
+ footer a {
110
+ color: var(--muted);
111
+ font-size: 0.88rem;
112
+ font-weight: 650;
113
+ text-decoration: none;
114
+ transition: color 180ms ease, border-color 180ms ease, background 180ms ease;
115
+ }
116
+
117
+ nav a:hover,
118
+ footer a:hover {
119
+ color: var(--text);
120
+ }
121
+
122
+ nav .nav-cta {
123
+ padding: 0.58rem 0.9rem;
124
+ border: 1px solid var(--border);
125
+ border-radius: 0.5rem;
126
+ }
127
+
128
+ nav .nav-cta:hover {
129
+ border-color: var(--primary);
130
+ background: rgb(56 189 248 / 8%);
131
+ }
132
+
133
+ .hero {
134
+ display: grid;
135
+ min-height: 42rem;
136
+ grid-template-columns: 1.08fr 0.92fr;
137
+ align-items: center;
138
+ gap: clamp(3rem, 7vw, 6rem);
139
+ padding-block: 6rem;
140
+ }
141
+
142
+ .hero > *,
143
+ .split > *,
144
+ .policy-section > * {
145
+ min-width: 0;
146
+ }
147
+
148
+ .eyebrow,
149
+ .kicker {
150
+ margin: 0 0 1rem;
151
+ color: var(--primary-strong);
152
+ font-family: var(--mono);
153
+ font-size: 0.75rem;
154
+ font-weight: 700;
155
+ letter-spacing: 0.11em;
156
+ text-transform: uppercase;
157
+ }
158
+
159
+ .eyebrow {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 0.65rem;
163
+ }
164
+
165
+ .eyebrow::before {
166
+ width: 0.5rem;
167
+ height: 0.5rem;
168
+ border-radius: 50%;
169
+ background: var(--primary);
170
+ box-shadow: 0 0 0 0.3rem rgb(56 189 248 / 12%);
171
+ content: "";
172
+ }
173
+
174
+ h1,
175
+ h2,
176
+ h3,
177
+ p {
178
+ margin-top: 0;
179
+ }
180
+
181
+ h1,
182
+ h2,
183
+ h3 {
184
+ line-height: 1.08;
185
+ }
186
+
187
+ h1 {
188
+ max-width: 13ch;
189
+ margin-bottom: 1.7rem;
190
+ font-size: clamp(3rem, 6vw, 5.3rem);
191
+ letter-spacing: -0.065em;
192
+ overflow-wrap: anywhere;
193
+ }
194
+
195
+ h1 em {
196
+ color: var(--primary-strong);
197
+ font-style: normal;
198
+ }
199
+
200
+ h2 {
201
+ margin-bottom: 1.2rem;
202
+ font-size: clamp(2rem, 4vw, 3.35rem);
203
+ letter-spacing: -0.045em;
204
+ }
205
+
206
+ h3 {
207
+ margin-bottom: 0.7rem;
208
+ font-size: 1.2rem;
209
+ letter-spacing: -0.02em;
210
+ }
211
+
212
+ .hero-lede,
213
+ .section-heading > p:last-child,
214
+ .policy-copy > p,
215
+ .boundary > p:last-child,
216
+ .cta > p {
217
+ max-width: 65ch;
218
+ color: var(--muted);
219
+ }
220
+
221
+ .hero-lede {
222
+ max-width: 58ch;
223
+ margin-bottom: 2rem;
224
+ font-size: 1.08rem;
225
+ }
226
+
227
+ .hero-actions {
228
+ display: flex;
229
+ flex-wrap: wrap;
230
+ gap: 0.8rem;
231
+ }
232
+
233
+ .button {
234
+ display: inline-flex;
235
+ min-height: 2.9rem;
236
+ align-items: center;
237
+ justify-content: center;
238
+ padding: 0.7rem 1.1rem;
239
+ border: 1px solid transparent;
240
+ border-radius: 0.55rem;
241
+ font-size: 0.9rem;
242
+ font-weight: 750;
243
+ text-decoration: none;
244
+ transition: border-color 180ms ease, background 180ms ease, color 180ms ease;
245
+ }
246
+
247
+ .button-primary {
248
+ background: var(--primary);
249
+ color: #04283a;
250
+ }
251
+
252
+ .button-primary:hover {
253
+ background: var(--primary-strong);
254
+ }
255
+
256
+ .button-secondary {
257
+ border-color: var(--border);
258
+ background: rgb(255 255 255 / 2%);
259
+ color: var(--text);
260
+ }
261
+
262
+ .button-secondary:hover {
263
+ border-color: var(--primary);
264
+ background: rgb(56 189 248 / 7%);
265
+ }
266
+
267
+ .support-list {
268
+ display: flex;
269
+ flex-wrap: wrap;
270
+ gap: 0.65rem 1.4rem;
271
+ margin: 2rem 0 0;
272
+ padding: 0;
273
+ color: var(--muted);
274
+ font-family: var(--mono);
275
+ font-size: 0.73rem;
276
+ list-style: none;
277
+ }
278
+
279
+ .support-list li::before {
280
+ display: inline-block;
281
+ width: 0.4rem;
282
+ height: 0.4rem;
283
+ margin-right: 0.45rem;
284
+ border-radius: 50%;
285
+ background: var(--primary);
286
+ content: "";
287
+ vertical-align: 0.05rem;
288
+ }
289
+
290
+ .terminal,
291
+ .code-panel {
292
+ overflow: hidden;
293
+ border: 1px solid var(--border);
294
+ border-radius: 0.85rem;
295
+ background: var(--bg-deep);
296
+ box-shadow: 0 2rem 5rem rgb(0 0 0 / 32%);
297
+ }
298
+
299
+ .terminal {
300
+ position: relative;
301
+ max-width: 100%;
302
+ }
303
+
304
+ .terminal::before {
305
+ position: absolute;
306
+ z-index: -1;
307
+ inset: -2rem;
308
+ border-radius: 50%;
309
+ background: rgb(56 189 248 / 9%);
310
+ content: "";
311
+ filter: blur(3rem);
312
+ }
313
+
314
+ .terminal-bar {
315
+ display: flex;
316
+ align-items: center;
317
+ gap: 0.42rem;
318
+ min-height: 2.65rem;
319
+ padding-inline: 1rem;
320
+ border-bottom: 1px solid var(--border);
321
+ background: var(--surface);
322
+ }
323
+
324
+ .terminal-bar::before {
325
+ width: 2.5rem;
326
+ height: 0.55rem;
327
+ background: radial-gradient(circle, #496272 0 0.25rem, transparent 0.28rem) 0 0 / 0.83rem 100%;
328
+ content: "";
329
+ }
330
+
331
+ .terminal-bar p {
332
+ margin: 0 0 0 0.45rem;
333
+ color: var(--muted);
334
+ font-family: var(--mono);
335
+ font-size: 0.68rem;
336
+ }
337
+
338
+ pre {
339
+ margin: 0;
340
+ overflow-wrap: anywhere;
341
+ font-family: var(--mono);
342
+ line-height: 1.7;
343
+ white-space: pre-wrap;
344
+ }
345
+
346
+ .terminal pre {
347
+ min-height: 20rem;
348
+ padding: 1.5rem;
349
+ color: #d9e9f2;
350
+ font-size: clamp(0.68rem, 1.3vw, 0.78rem);
351
+ }
352
+
353
+ .prompt,
354
+ .hint,
355
+ .key {
356
+ color: var(--primary-strong);
357
+ }
358
+
359
+ .accent {
360
+ color: var(--accent);
361
+ }
362
+
363
+ .failure {
364
+ color: var(--danger);
365
+ }
366
+
367
+ .muted {
368
+ color: var(--muted);
369
+ }
370
+
371
+ .section {
372
+ padding-block: 6.5rem;
373
+ border-top: 1px solid var(--border);
374
+ scroll-margin-top: 1rem;
375
+ }
376
+
377
+ .section-heading {
378
+ max-width: 46rem;
379
+ margin-bottom: 3rem;
380
+ }
381
+
382
+ .feature-grid {
383
+ display: grid;
384
+ grid-template-columns: repeat(3, 1fr);
385
+ gap: 1rem;
386
+ }
387
+
388
+ .feature-card {
389
+ min-height: 18rem;
390
+ padding: 1.7rem;
391
+ border: 1px solid var(--border);
392
+ border-radius: 0.75rem;
393
+ background: linear-gradient(145deg, rgb(255 255 255 / 3%), transparent);
394
+ }
395
+
396
+ .feature-card p {
397
+ color: var(--muted);
398
+ }
399
+
400
+ .feature-card code,
401
+ .mode-list code {
402
+ color: var(--primary-strong);
403
+ font-family: var(--mono);
404
+ font-size: 0.78rem;
405
+ }
406
+
407
+ .feature-index {
408
+ display: block;
409
+ margin-bottom: 4rem;
410
+ color: var(--accent);
411
+ font-family: var(--mono);
412
+ font-size: 0.72rem;
413
+ }
414
+
415
+ .split {
416
+ display: grid;
417
+ grid-template-columns: 0.8fr 1.2fr;
418
+ gap: clamp(3rem, 8vw, 7rem);
419
+ }
420
+
421
+ .steps {
422
+ margin: 0;
423
+ padding: 0;
424
+ list-style: none;
425
+ }
426
+
427
+ .steps > li {
428
+ padding: 0 0 2.2rem;
429
+ }
430
+
431
+ .steps > li + li {
432
+ padding-top: 2.2rem;
433
+ border-top: 1px solid var(--border);
434
+ }
435
+
436
+ .step-heading {
437
+ display: flex;
438
+ align-items: center;
439
+ gap: 0.8rem;
440
+ margin-bottom: 1rem;
441
+ }
442
+
443
+ .step-heading span {
444
+ display: grid;
445
+ width: 1.8rem;
446
+ height: 1.8rem;
447
+ place-items: center;
448
+ border: 1px solid var(--border);
449
+ border-radius: 50%;
450
+ color: var(--primary-strong);
451
+ font-family: var(--mono);
452
+ font-size: 0.7rem;
453
+ }
454
+
455
+ .step-heading h3 {
456
+ margin: 0;
457
+ }
458
+
459
+ .steps pre {
460
+ padding: 1.1rem 1.2rem;
461
+ border: 1px solid var(--border);
462
+ border-radius: 0.55rem;
463
+ background: var(--bg-deep);
464
+ color: var(--text);
465
+ font-size: 0.78rem;
466
+ }
467
+
468
+ .mode-list {
469
+ display: grid;
470
+ grid-template-columns: repeat(2, 1fr);
471
+ gap: 0.6rem;
472
+ }
473
+
474
+ .mode-list p {
475
+ display: flex;
476
+ flex-direction: column;
477
+ margin: 0;
478
+ padding: 0.85rem;
479
+ border: 1px solid var(--border);
480
+ border-radius: 0.5rem;
481
+ }
482
+
483
+ .mode-list span {
484
+ color: var(--muted);
485
+ font-size: 0.78rem;
486
+ }
487
+
488
+ .policy-section {
489
+ display: grid;
490
+ grid-template-columns: 0.85fr 1.15fr;
491
+ align-items: center;
492
+ gap: clamp(3rem, 8vw, 7rem);
493
+ }
494
+
495
+ .text-link {
496
+ color: var(--primary-strong);
497
+ font-weight: 700;
498
+ text-underline-offset: 0.25rem;
499
+ }
500
+
501
+ .code-panel > p {
502
+ margin: 0;
503
+ padding: 0.8rem 1.2rem;
504
+ border-bottom: 1px solid var(--border);
505
+ background: var(--surface);
506
+ color: var(--muted);
507
+ font-family: var(--mono);
508
+ font-size: 0.7rem;
509
+ }
510
+
511
+ .code-panel pre {
512
+ padding: 1.4rem;
513
+ color: #d9e9f2;
514
+ font-size: 0.76rem;
515
+ }
516
+
517
+ .flow {
518
+ display: grid;
519
+ grid-template-columns: repeat(3, 1fr);
520
+ }
521
+
522
+ .flow > div {
523
+ position: relative;
524
+ padding: 2rem 2rem 1rem 0;
525
+ border-top: 1px solid var(--primary);
526
+ }
527
+
528
+ .flow > div:not(:last-child) {
529
+ margin-right: 2rem;
530
+ }
531
+
532
+ .flow span {
533
+ display: block;
534
+ margin-bottom: 3rem;
535
+ color: var(--primary-strong);
536
+ font-family: var(--mono);
537
+ font-size: 0.7rem;
538
+ }
539
+
540
+ .flow p {
541
+ color: var(--muted);
542
+ }
543
+
544
+ .boundary {
545
+ position: relative;
546
+ margin-block: 2rem 7rem;
547
+ padding: clamp(2rem, 5vw, 4rem);
548
+ overflow: hidden;
549
+ border: 1px solid rgb(251 146 60 / 42%);
550
+ border-radius: 0.9rem;
551
+ background: linear-gradient(135deg, rgb(251 146 60 / 10%), rgb(251 146 60 / 2%));
552
+ }
553
+
554
+ .boundary::after {
555
+ position: absolute;
556
+ right: -2rem;
557
+ bottom: -7rem;
558
+ color: rgb(251 146 60 / 7%);
559
+ content: "!";
560
+ font-family: var(--mono);
561
+ font-size: 18rem;
562
+ font-weight: 800;
563
+ line-height: 1;
564
+ }
565
+
566
+ .boundary h2,
567
+ .boundary p {
568
+ position: relative;
569
+ z-index: 1;
570
+ max-width: 48rem;
571
+ }
572
+
573
+ .boundary .kicker {
574
+ color: var(--accent);
575
+ }
576
+
577
+ .cta {
578
+ padding: 7rem 2rem;
579
+ border-top: 1px solid var(--border);
580
+ text-align: center;
581
+ }
582
+
583
+ .cta p {
584
+ margin-inline: auto;
585
+ }
586
+
587
+ .cta .hero-actions {
588
+ justify-content: center;
589
+ margin-top: 2rem;
590
+ }
591
+
592
+ footer {
593
+ display: flex;
594
+ min-height: 8rem;
595
+ align-items: center;
596
+ justify-content: space-between;
597
+ gap: 2rem;
598
+ border-top: 1px solid var(--border);
599
+ color: var(--muted);
600
+ font-size: 0.8rem;
601
+ }
602
+
603
+ footer p {
604
+ margin: 0;
605
+ }
606
+
607
+ footer div {
608
+ display: flex;
609
+ gap: 1.2rem;
610
+ }
611
+
612
+ @media (max-width: 900px) {
613
+ nav > a:not(.nav-cta) {
614
+ display: none;
615
+ }
616
+
617
+ .hero,
618
+ .split,
619
+ .policy-section {
620
+ grid-template-columns: 1fr;
621
+ }
622
+
623
+ .hero {
624
+ padding-block: 4.5rem;
625
+ }
626
+
627
+ .hero-copy {
628
+ max-width: 44rem;
629
+ }
630
+
631
+ .terminal {
632
+ max-width: 42rem;
633
+ }
634
+
635
+ .feature-grid {
636
+ grid-template-columns: 1fr;
637
+ }
638
+
639
+ .feature-card {
640
+ min-height: 0;
641
+ }
642
+
643
+ .feature-index {
644
+ margin-bottom: 2.5rem;
645
+ }
646
+ }
647
+
648
+ @media (max-width: 640px) {
649
+ .site-header,
650
+ main,
651
+ footer {
652
+ width: min(calc(100% - 2rem), var(--max-width));
653
+ }
654
+
655
+ .site-header {
656
+ min-height: 4.75rem;
657
+ }
658
+
659
+ nav .nav-cta {
660
+ padding: 0.5rem 0.7rem;
661
+ }
662
+
663
+ h1 {
664
+ font-size: clamp(2.65rem, 14vw, 4rem);
665
+ }
666
+
667
+ .hero {
668
+ gap: 3.5rem;
669
+ padding-block: 3.5rem 5rem;
670
+ }
671
+
672
+ .section {
673
+ padding-block: 5rem;
674
+ }
675
+
676
+ .terminal pre,
677
+ .code-panel pre {
678
+ padding: 1rem;
679
+ font-size: 0.67rem;
680
+ }
681
+
682
+ .mode-list,
683
+ .flow {
684
+ grid-template-columns: 1fr;
685
+ }
686
+
687
+ .flow > div:not(:last-child) {
688
+ margin-right: 0;
689
+ }
690
+
691
+ .flow span {
692
+ margin-bottom: 1.8rem;
693
+ }
694
+
695
+ .boundary {
696
+ margin-bottom: 5rem;
697
+ }
698
+
699
+ footer {
700
+ flex-direction: column;
701
+ align-items: flex-start;
702
+ justify-content: center;
703
+ padding-block: 2rem;
704
+ }
705
+ }
706
+
707
+ @media (prefers-reduced-motion: reduce) {
708
+ html {
709
+ scroll-behavior: auto;
710
+ }
711
+
712
+ *,
713
+ *::before,
714
+ *::after {
715
+ scroll-behavior: auto !important;
716
+ transition-duration: 0.01ms !important;
717
+ }
718
+ }
@@ -0,0 +1,13 @@
1
+ network:
2
+ default: deny
3
+ allow:
4
+ - host: 127.0.0.1
5
+ ports: [5432]
6
+ write:
7
+ default: deny
8
+ allow: [tmp, log, coverage, /tmp]
9
+ exec:
10
+ default: allow
11
+ deny: [/usr/bin/curl, /usr/bin/wget]
12
+ on_violation: fail
13
+ report_path: tmp/straycall.json
data/examples/rspec.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tmpdir"
4
+ require "straycall"
5
+
6
+ Straycall.configure do |config|
7
+ config.allow_loopback ports: [5432]
8
+ config.allow_write_under "tmp", "log", "coverage", Dir.tmpdir
9
+ config.deny_write_elsewhere!
10
+ config.report_path = "tmp/straycall.json"
11
+ end
12
+
13
+ require "straycall/rspec"