apt
manpage of Ubuntu recently, which, for some reason, uses blue text in one place:
Ah, so apparently they donāt like writing manpages anymore and instead use XML:
https://salsa.debian.org/apt-team/apt/-/blob/main/doc/apt.8.xml
And then they use XSLT on top and what not:
https://salsa.debian.org/apt-team/apt/-/blob/main/doc/manpage-style.xsl.cmake.in
Itās not even explicitly blue:
https://salsa.debian.org/apt-team/apt/-/blob/main/doc/apt.ent?ref_type=heads#L17
Abstractions upon abstractions upon abstractions.
Look at that, a mate just told me: What if YAML had even more security issues!? YAMLScript! https://yamlscript.org/doc/cheat/
Hereās an example of X11/Xlib being old and archaic.
X11 knows the data type ācardinalā. For example, the window property _NET_WM_ICON
(which holds image data for icons) is an array of ācardinalā. I am already not really familiar with that word and Iām assuming that it comes from mathematics:
https://en.wikipedia.org/wiki/Cardinal_number
(It could also be a bird, but probably not: https://en.wikipedia.org/wiki/Cardinalidae)
We would probably call this an āintegerā today.
EWMH says that icons are arrays of cardinals and that theyāre 32-bit numbers:
https://specifications.freedesktop.org/wm-spec/latest-single/#id-1.6.13
So itās something like 0x11223344
with 0x11
being the alpha channel, 0x22
is red, and so on.
You would assume that, when you retrieve such an array from the X11 server, youād get an array of uint32_t
, right?
Nope.
Xlib is so old, they use char
for 8-bit stuff, short int
for 16-bit, and long int
for 32-bit:
That is congruent with the general C data types, so it does make sense:
https://en.wikipedia.org/wiki/C_data_types
Now the funny thing is, on modern x86_64
, the type long int
is actually 64 bits wide.
The result is that every pixel in a Pixmap, for example, is twice as large in memory as it would need to be. Just because Xlib uses long int
, because uint32_t
didnāt exist, yet.
And this is something that I wouldnāt know how to fix without breaking clients.
@lyse@lyse.isobeef.org @kat@yarn.girlonthemoon.xyz I spent so much time in the past figuring out if something is a dict or a list in YAML, for example.
What are the types in this example?
items:
- part_no: A4786
descrip: Water Bucket (Filled)
price: 1.47
quantity: 4
- part_no: E1628
descrip: High Heeled "Ruby" Slippers
size: 8
price: 133.7
quantity: 1
items
is a dict containing ⦠a list of two other dicts? Right?
It is quite hard for me to grasp the structure of YAML docs. š¢
The big advantage of YAML (and JSON and TOML) is that itās much easier to write code for those formats, than it is with XML. json.loads()
and youāre done.
After many weeks and probably at least a hundred hours of research, discussions and in-person viewing, I think Iāve finally come up with my Final Choices (shortlist) of a Hybrid Camper / Caravan that I think will suit my family and that Iāll enjoy (far less work for me to setup and teardown). The one at the top of the list Iām leaning towards os the SWAG SCT16 Family 4B
#Camping #CampersHTTP referrers are quite broken, arenāt they?
Because of that recent storm on my blog, I had a peek at them. Thereās a lot of garbage in there. For example, https://docs.freebsd.org/en/books/handbook/disks-virtual.html is supposed to refer to one of my blog posts ā¦
Whatās going on here?
Been spending a lot of time researching campers as I want to / plan to upgrade our current Camper Trailoer (forward fold) Stoney Creek XL-FF6 to a slightly larger Hybrid Camper/Caravan with ensuite, internal kitchenette, external full hitchen, pop-top roof and twin bunks.
This is the summary and whittling down of my research so far: https://wiki.mills.io/s/1103bc9c-dd75-4a98-b64b-8dadc5b0e51f/doc/comparision-Ln03Moiibq
I did a ālectureā/āworkshopā about this at work today. 16-bit DOS, real mode. š¾ Pretty cool and the audience (devs and sysadmins) seemed quite interested. š„³
- People used the Intel docs to figure out the instruction encodings.
- Then they wrote a little DOS program that exits with a return code and they used uhex in DOSBox to do that. Yes, we wrote a COM file manually, no Assembler involved. (Many of them had never used DOS before.)
- DEBUG from FreeDOS was used to single-step through the program, showing what it does.
- This gets tedious rather quickly, so we switched to SVED from SvarDOS for writing the rest of the program in Assembly language. nasm worked great for us.
- At the end, we switched to BIOS calls instead of DOS syscalls to demonstrate that the same binary COM file works on another OS. Also a good opportunity to talk about bootloaders a little bit.
- (I think they even understood the basics of segmentation in the end.)
The 8086 / 16-bit real-mode DOS is a great platform to explain a lot of the fundamentals without having to deal with OS semantics or executable file formats.
Now that was a lot of fun. š„³ Itās very rare that we do something like this, sadly. I love doing this kind of low-level stuff.
Okay, hereās a thing I like about Rust: Returning things as Option
and error handling. (Or the more complex Result
, but itās easier to explain with Option
.)
fn mydiv(num: f64, denom: f64) -> Option<f64> {
// (Letās ignore precision issues for a second.)
if denom == 0.0 {
return None;
} else {
return Some(num / denom);
}
}
fn main() {
// Explicit, verbose version:
let num: f64 = 123.0;
let denom: f64 = 456.0;
let wrapped_res = mydiv(num, denom);
if wrapped_res.is_some() {
println!("Unwrapped result: {}", wrapped_res.unwrap());
}
// Shorter version using "if let":
if let Some(res) = mydiv(123.0, 456.0) {
println!("Hereās a result: {}", res);
}
if let Some(res) = mydiv(123.0, 0.0) {
println!("Huh, we divided by zero? This never happens. {}", res);
}
}
You canāt divide by zero, so the function returns an āerrorā in that case. (Option
isnāt really used for errors, IIUC, but the basic idea is the same for Result
.)
Option
is an enum. It can have the value Some
or None
. In the case of Some
, you can attach additional data to the enum. In this case, we are attaching a floating point value.
The caller then has to decide: Is the value None
or Some
? Did the function succeed or not? If it is Some
, the caller can do .unwrap()
on this enum to get the inner value (the floating point value). If you do .unwrap()
on a None
value, the program will panic and die.
The if let
version using destructuring is much shorter and, once you got used to it, actually quite nice.
Now the trick is that you must somehow handle these two cases. You must either call something like .unwrap()
or do destructuring or something, otherwise you canāt access the attached value at all. As I understand it, it is impossible to just completely ignore error cases. And the compiler enforces it.
(In case of Result
, the compiler would warn you if you ignore the return value entirely. So something like doing write()
and then ignoring the return value would be caught as well.)
@prologic@twtxt.net Iām trying to call some libc functions (because the Rust stdlib does not have an equivalent for getpeername()
, for example, so I donāt have a choice), so I have to do some FFI stuff and deal with raw pointers and all that, which is very gnarly in Rust ā because youāre not supposed to do this. Things like that are trivial in C or even Assembler, but I have not yet understood what Rust does under the hood. How and when does it allocate or free memory ⦠is the pointer that I get even still valid by the time I do the libc call? Stuff like that.
I hope that I eventually learn this over time ⦠but I get slapped in the face at every step. Itās very frustrating and Iām always this š¤ close to giving up (only to try again a year later).
Oh, yeah, yeah, I guess I could ājustā use some 3rd party library for this. socket2 gets mentioned a lot in this context. But I donāt want to. I literally need one getpeername()
call during the lifetime of my program, I donāt even do the socket()
, bind()
, listen()
, accept()
dance, I already have a fully functional file descriptor. Using a library for that is total overkill and Iād rather do it myself. (And look at the version number: 0.5.10
. The library is 6 years old but theyāre still saying: āNah, weāre not 1.0 yet, we reserve the right to make breaking changes with every new release.ā So many Rust libs are still unstable ā¦)
⦠and I could go on and on and on ⦠š¤£
fn sub(foo: &String) {
println!("We got this string: [{}]", foo);
}
fn main() {
// "Hello", 0x00, 0x00, "!"
let buf: [u8; 8] = [0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x00, 0x21];
// Create a string from the byte array above, interpret as UTF-8, ignore decoding errors.
let lossy_unicode = String::from_utf8_lossy(&buf).to_string();
sub(&lossy_unicode);
}
Create a string from a byte array, but the result isnāt a string, itās a cow š®, so you need another to_string()
to convert your āstringā into a string.
- https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf8_lossy
- https://doc.rust-lang.org/std/borrow/enum.Cow.html
I still have a lot to learn.
(into_owned()
instead of to_string()
also works and makes more sense to me, itās just that the compiler suggested to_string()
first, which led to this funny example.)
@lyse@lyse.isobeef.org Rust is so different and, at the same time, so complex ā itās not far fetched to assume that I simply donāt understand whatās going on here. The docs appear to be clear, but alas ⦠is it a bugs in the docs? Is it a lack of experience on my part? Who knows.
By the way, looks like there was a bit of a discussion regarding that name:
So I was using this function in Rust:
https://doc.rust-lang.org/std/path/struct.Path.html#method.display
Note the little 1.0.0
in the top right corner, which means that this function has been āstable since Rust version 1.0.0ā. Weāre at 1.87 now, so weāre good.
Then I compiled my program on OpenBSD with Rust 1.86, i.e. just one version behind, but well ahead of 1.0.0.
The compiler said that I was using an unstable library feature.
Turns out, that function internally uses this:
https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.display
And that is only available since Rust 1.87.
How was I supposed to know this? š¤Øš«©
@prologic@twtxt.net Yeah, itās difficult, you often donāt get what youād expect. They also make heavy use of 3rd party libraries. IIUC, for random numbers, they refer to this library. Iāve read many times that the Rust stdlib is intentionally minimalistic (to make it easier to maintain and port and all that).
Iām struggling with this, using 3rd party libs for so many things isnāt really my cup of tea. Iāll probably make my own tiny little āstandard libraryā. Itās silly, but I donāt see any other options. š¤·
Thanks, @movq@www.uninformativ.de! That seems to be much easier. Itās already implemented in the Python docs as examples of recvmsg(ā¦)
and sendmsg(ā¦)
:
- https://docs.python.org/3/library/socket.html#socket.socket.recvmsg
- https://docs.python.org/3/library/socket.html#socket.socket.sendmsg
I looked at them sooo many times in order to figure out why my SCM_CREDENTIALS
sending code didnāt work. :-D
@movq@www.uninformativ.de @kat@yarn.girlonthemoon.xyz @quark@ferengi.one In 2014 one person created protocol ii. Later it forked in IDEC. Why i said this? Because itās simple āfederatedā forum-like protocol where from your station fetch another every 5-10 minutes. Stations has topic-based channels like idec.talks, linux.16, haiku.os, zx.spectrum. In short itās FIDO but.. more modern? Documentation: https://github.com/idec-net/new-docs (mostly Russian, but you can use translator, also protocol already translated to english)
Confession:
Iāve never found microblogging like twtxt or the Fediverse or any other āmodernā social media to be truly fulfilling/satisfying.
The reason is that it is focused so much on people. You follow this or that person, everybody spends time making a nice profile page, the posts are all very āego-centricā. Seriously, it feels like everybody is on an ego-trip all the time (this is much worse on the Fediverse, not so much here on twtxt).
I miss the days of topic-based forums/groups. A Linux forum here, a forum about programming there, another one about a certain game. Stuff like that. That was really great ā and it didnāt even suffer from the need to federate.
Sadly, most of these forums are dead now. Especially the nerds spend a lot of time on the Fediverse now and have abandoned forums almost completely.
On Mastodon, you can follow hashtags, which somewhat emulates a topic-based experience. But itās not that great and the protocol isnāt meant to be used that way (just read the snac2 docs on this issue). And the concept of ālikesā has eliminated lots of the actual user interaction. ā¹ļø
Nobody writes emails by hand using RFC 5322 anymore, nor do we manually send them through telnet and SMTP commands. The days of crafting emails in raw format and dialing into servers are long gone. Modern email clients and services handle it all seamlessly in the background, making email easier than ever to send and receiveāwithout needing to understand the protocols or formats behind it! #Email #SMTP #RFC #Automation
@kat@yarn.girlonthemoon.xyz I skimmed through the gamja docs and they say you need an āIRC WebSocket serverā ā no idea what that is. Does gamja not speak IRC directly but essentially āIRC over HTTPā? Curious. š¤
7k words of docs on deploying a livejournal folk. you absolutely want to read 7 thousand words of me forcing dreamwidth into production shape in docker https://stash.4-walls.net/selfhostdw/
si4er3q
. See https://twtxt.dev/exts/twt-hash.html, a timezone offset of +00:00
or -00:00
must be replaced by Z
.
just a note that we are doing that on PHP: https://github.com/eapl-gemugami/twtxt-php/blob/master/docs/03-hash-extension.md#php-72
That PHP snippet could be merged into https://twtxt.dev/exts/twt-hash.html
@thecanine@twtxt.net I found it! This looks like colored easter eggs when squinting.
Hi! For anyone following the Request for Comments on an improved syntax for replies and threads, Iāve made a comparative spreadsheet with the 4 proposals so far. It shows a syntax example, and top pros and cons Iāve found:
https://docs.google.com/spreadsheets/d/1KOUqJ2rNl_jZ4KBVTsR-4QmG1zAdKNo7QXJS1uogQVo/edit?gid=0#gid=0
Feel free to propose another collaborative platform (for those without a G account), and also share your comments and analysis in the spreadsheet or in Gitea.
Itās been a long time since Iāve seen a project on Hacker News with 1300 votes (every few days something comes up with 600).
https://github.com/suitenumerique/docs
@prologic@twtxt.net I believe @andros@twtxt.andros.dev is referring to the one on the original twtxt docs . Iāve been meaning to contribute to the discussion on the git but Iām just lazy š
amma throw in a little something in a minute Poke a bee hive and run away style
š
here are a few ideas you might take into consideration when designing a secure IM https://developer.virgilsecurity.com/docs/e3kit/fundamentals/secure-instant-messaging/
Obviously if youāve worked on something similar, you already know it, he
@bender@twtxt.net oh yeah i remember that part of the docs lol! honestly yeah i think sqlite is fine for the number of users i have which is like, 5 including me, and active users is just⦠me, but if i were to have more active users i could always spin up a separate instance as jank as that is
asciinema is really cool. thought about self hosting my own upload site which they have docs for but i donāt need to host everything even if itād be a fun project. the default/main site is fine enough for me when i wonāt be uploading a whole lot.
@eapl.me@eapl.me A way to have a more blueskyāish handles in twtxt could be to take inspiration from Bridgy Fed and say: If NICK = DOMAIN then only show @DOMAIN
So instead of @eapl.me@eapl.me it will just be @eapl.me
And it event seem that it will not break webfinger lookup: https://webfinger.net/lookup/?resource=%40darch.dk (at least not for how Iāve implemented webfinger on my sever for a single user;)
@quark@ferengi.one It looks like the part about traditional topics has been removed from that page. Here is an old version that mentions it: https://web.archive.org/web/20221211165458/https://dev.twtxt.net/doc/twtsubjectextension.html . Still, I donāt see any description of what is actually allowed between the parentheses. May be worth noting that twtxt.net is displaying the twts with the subject stripped, so some piece of code is recognizing it as a subject (or, at least, something to be removed).
@falsifian@www.falsifian.org based on Twt Subject Extension, your subject is invalid. You can have custom subjects, that is, not a valid hash, but you simply canāt put anything, and expect it to be treated as a TwtSubject
, me thinks.
HTTPS is supposed to do [verification] anyway.
TLS provides verification that nobody is tampering with or snooping on your connection to a server. It doesnāt, for example, verify that a file downloaded from server A is from the same entity as the one from server B.
I was confused by this response for a while, but now I think I understand what youāre getting at. You are pointing out that with signed feeds, I can verify the authenticity of a feed without accessing the original server, whereas with HTTPS I canāt verify a feed unless I download it myself from the origin server. Is that right?
I.e. if the HTTPS origin server is online and I donāt mind taking the time and bandwidth to contact it, then perhaps signed feeds offer no advantage, but if the origin server might not be online, or I want to download a big archive of lots of feeds at once without contacting each server individually, then I need signed feeds.
feed locations [being] URLs gives some flexibility
It does give flexibility, but perhaps we should have made them URIs instead for even more flexibility. Then, you could use a tag URI,
urn:uuid:*
, or a regular old URL if you wanted to. The spec seems to indicate that theurl
tag should be a working URL that clients can use to find a copy of the feed, optionally at multiple locations. Iām not very familiar with IP{F,N}S but if it ensures you own an identifier forever and that identifier points to a current copy of your feed, it could be a great way to fix it on an individual basis without breaking any specs :)
Iām also not very familiar with IPFS or IPNS.
I havenāt been following the other twts about signatures carefully. I just hope whatever you smart people come up with will be backwards-compatible so it still works if Iām too lazy to change how I publish my feed :-)
I just manually followed the steps at https://dev.twtxt.net/doc/twthashextension.html and got 6mdqxrq. I wonder what happened. Did @cuaxolo@sunshinegardens.org edit the twt in some subtle way after twtxt.net downloaded it? I couldnāt spot a diff, other than ā appearing as ā on yarn.social, which I assume is a transformation done by twtxt.net.
@prologic@twtxt.net Yes, fetching the twt by hash from some service could be a good alternative, in case the twt I have does not @-mention the source. (Besides yarnd, maybe this should be part of the registry API? I donāt see fetch-by-hash in the registry API docs.)
Thanks @prologic@twtxt.net, I also just manage to get my own version of webmentions working. Please have a read at Webmentions vs. Custom Mentions Spec for Twtxt/Yarn - HedgeDoc and User Lookup for Twtxt/Yarn - Webfinger or Decentralized Identifiers (DIDs) - HedgeDoc for how it sorta works
Did another write up on #webfinger and DIDs for twtxt/yarn that you can read and edit/comment in: User lookup for twtxt/yarn - Webfinger or Decentralized Identifiers (DIDs) - HedgeDoc
Iāve gathers my ideas about mentions for twtxt/yarn here: Webmentions vs. custom mentions spec for twtxt/yarn - HedgeDoc
You are welcome to edit and comment in the doc, so our ideas are not fragment into a bunch of treads
@eapl.me@eapl.me I have many fond memories of Turbo pascal and Turbo C(++). They really did have a great help system. And debug tools! Its rare for language docs to be as approachable. QBasic was great. As was PHP docs when I first came into web.
Just finished writing my doc on how Iām using Parabola to export LJ to Plume https://ouvaton.link/F0KxT5
@abucci@anthony.buc.ci see here in the okta docs: https://developer.okta.com/docs/reference/api/webfinger/ they are adding a prefix to the acct
ahh this is useful https://go.dev/doc/modules/managing-dependencies. the go culture doesnāt typically have large dependency graphs like Ruby or JS.
Ah git-bug! Ive chatted with the creator when he was working on the graphql parts. Its working with git objects directly sorta like how git-repo does code reviews. Its a pretty neat idea for storing data along side the branches. I believe they donāt add a disconnected branch to avoid data getting corrupted by merging branches or something like that.
so I may have farked up twtxt on oh.mg when I started moving docs, if you can see this the new version is at https://txt.om.gay/twtxt.txt
Did some work on WKD handling. Can update keys with HKP posts :) Ugh need to work on docs and unit tests. Boooorrring.
initial ugens page added to !monolith wiki, with link to woven ugens scheme file. the first non-C woven file in monolith. [[/proj/monolith/wiki/ugens]]. #docs #updates
Parapsychology in the PRC 1979-1989 https://www.cia.gov/library/readingroom/docs/CIA-RDP96-00789R002600290003-0.pdf
Dr. Alan Kay on the Meaning of āObject-Oriented Programmingā http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
OFFICIAL TRAILER - IN SEARCH OF DARKNESS - THE DEFINITIVE ā80s HORROR DOC - YouTube https://www.youtube.com/watch?v=9AKnO2hr7b0
Systems Software Research is Irrelevant (aka utah2000 or utah2k) http://doc.cat-v.org/bell_labs/utah2000/utah2000.html
Cyberfeminist Index (~1990s-present) - Google Sheets https://docs.google.com/spreadsheets/d/1q_ZlbZhstBTfnZL4QP11ebivXgsvrf8shuG-QX146nw/edit#gid=1949020646
riptide/guide.adoc at master Ā· sagebind/riptide Ā· GitHub https://github.com/sagebind/riptide/blob/master/docs/guide.adoc
GXemul - Documentation (0.6.1) http://gavare.se/gxemul/gxemul-stable/doc/guestoses.html#sprite
From Satori to Silicon Valley https://web.stanford.edu/dept/SUL/sites/mac/primary/docs/satori/machines.html
From Satori to Silicon Valley https://web.stanford.edu/dept/SUL/sites/mac/primary/docs/satori/taste.html
From Satori to Silicon Valley https://web.stanford.edu/dept/SUL/sites/mac/primary/docs/satori/organic.html
inferno@interstice.com and inferno@artnet.com.br list archives http://doc.cat-v.org/inferno/historical_documents/mailing_lists/interstice/
Acid: A Debugger Built From A Language http://doc.cat-v.org/plan_9/4th_edition/papers/acidpaper
Native Kernel Debugging with Acid http://doc.cat-v.org/inferno/4th_edition/kernel_debugging/
The Inferno Shell http://doc.cat-v.org/inferno/4th_edition/inferno_shell
Program Development under Inferno http://doc.cat-v.org/inferno/4th_edition/development
The Styx Architecture for Distributed Systems http://doc.cat-v.org/inferno/4th_edition/styx
The Inferno Operating System http://doc.cat-v.org/inferno/4th_edition/inferno_OS
A Descent into Limbo http://doc.cat-v.org/inferno/4th_edition/limbo_language/descent
The Limbo Programming Language http://doc.cat-v.org/inferno/4th_edition/limbo_language/limbo
The Organization of Networks in Plan 9 http://doc.cat-v.org/plan_9/4th_edition/papers/net/
Acme: A User Interface for Programmers http://doc.cat-v.org/plan_9/4th_edition/papers/acme/
The Text Editor sam http://doc.cat-v.org/plan_9/4th_edition/papers/sam/
Haiku Human Interface Guidelines https://www.haiku-os.org/docs/HIG/index.xml
MenuetOS http://www.menuetos.net/docs.htm
Specification gaming examples in AI - master list https://docs.google.com/spreadsheets/u/1/d/e/2PACX-1vRPiprOaC3HsCf5Tuum8bRfzYUiKLRqJmbOoC-32JorNdfyTiRRsR7Ea5eWtvsWzuxo8bjOxCG84dAg/pubhtml
Apparently, the Bell Labs āsqueakā UI language is unrelated to the Smalltalk dialect of the same name, despite both being message-passing systems with strong GUI support http://doc.cat-v.org/bell_labs/squeak/squeak.pdf
Improving the Discussion Board - Lehigh University https://www.lehigh.edu/~indiscus/doc_guidelines.html
programmer interfaces - Google Slides https://docs.google.com/presentation/d/1MD-CgzODFWzdpnYXr8bEgysfDmb8PDV6iCAjH5JIvaI/edit#slide=id.g1da0625f1b_0_56
Prolog Basics Class https://docs.google.com/forms/d/e/1FAIpQLSf3KMzm7tx_py67vc__JgoO1imlscNkVQ7_6ppvxOCoTWOUVQ/viewform
Doc Searls Weblog Ā· GDPR will pop the adtech bubble https://blogs.harvard.edu/doc/2018/05/12/gdpr/
Somebody on mastodon linked me to this, and itās a fantastic syllabus. Highly recommend reading ALL of these: https://paper.dropbox.com/doc/hyperreal-VRp8uyehhIOdW3tET3O64
Doc Searls Weblog Ā· Facebookās Cambridge Analytica problems are nothing compared to whatās coming for all of online publishing https://blogs.harvard.edu/doc/2018/03/23/nothing/
Watch This Doc on Alien Gangsters and the āBiggest Story Never Toldā - Motherboard https://motherboard.vice.com/en_us/article/43nzng/roger-leir-alien-implant-ufo-abduction
Tech Ethics Curriculum - Google Sheets https://docs.google.com/spreadsheets/d/1jWIrA8jHz5fYAW4h9CkUD8gKS5V98PDJDymRf8d9vKI/edit?imm_mid=0f852c
Fact Checks | Search https://developers.google.com/search/docs/data-types/factcheck
The Quartz Directory of Reliable Data - Google Sheets https://docs.google.com/spreadsheets/d/1hU7Snj4KZ-ppyy388l-sV4I26n4yGVb8xYnygPOS-5k/edit#gid=1436509184
Data Is Plural ā Structured Archive - Google Sheets https://docs.google.com/spreadsheets/d/1wZhPLMCHKJvwOkP4juclhjFgqIY8fQFMemwKL2c64vk/edit#gid=0