Question to all you Gophers out there: How do you deal with custom errors that include more information and different kinds of matching them?
I started with a simple var ErrPermissionNotAllowed = errors.New("permission not allowed"). In my function I then wrap that using fmt.Errorf("%w: %v", ErrPermissionNotAllowed, failedPermissions). I can match this error using errors.Is(err, ErrPermissionNotAllowed). So far so good.
Now for display purposes I’d also like to access the individual permissions that could not be assigned. Parsing the error message is obviously not an option. So I thought, I create a custom error type, e.g. type PermissionNotAllowedError []Permission and give it some func (e PermissionNotAllowedError) Error() string { return fmt.Sprintf("permission not allowed: %v", e) }. My function would then return this error instead: PermissionNotAllowedError{failedPermissions}
At some layers I don’t care about the exact permissions that failed, but at others I do, at least when accessing them. A custom func (e PermissionNotAllowedError) Is(target err) bool could match both the general ErrPermissionNotAllowed as well as the PermissionNotAllowedError. Same with As(…). For testing purposes the PermissionNotAllowedError would then also try to match the included permissions, so assertions in tests would work nicely. But having two different errors for different matching seems not very elegant at all.
Did you ever encounter this scenario before? How did you address this? Is my thinking flawed?
Introduction to SELinux
SELinux is the most popular Linux Security Module used to isolate and protect system components from one another. Learn about different access control systems and Linux security as I introduce the foundations of a popular type system. ⌘ Read more
An official FBI document dated January 2021, obtained by the American association “Property of People” through the Freedom of Information Act.

This document summarizes the possibilities for legal access to data from nine instant messaging services: iMessage, Line, Signal, Telegram, Threema, Viber, WeChat, WhatsApp and Wickr. For each software, different judicial methods are explored, such as subpoena, search warrant, active collection of communications metadata (“Pen Register”) or connection data retention law (“18 USC§2703”). Here, in essence, is the information the FBI says it can retrieve:
Apple iMessage: basic subscriber data; in the case of an iPhone user, investigators may be able to get their hands on message content if the user uses iCloud to synchronize iMessage messages or to back up data on their phone.
Line: account data (image, username, e-mail address, phone number, Line ID, creation date, usage data, etc.); if the user has not activated end-to-end encryption, investigators can retrieve the texts of exchanges over a seven-day period, but not other data (audio, video, images, location).
Signal: date and time of account creation and date of last connection.
Telegram: IP address and phone number for investigations into confirmed terrorists, otherwise nothing.
Threema: cryptographic fingerprint of phone number and e-mail address, push service tokens if used, public key, account creation date, last connection date.
Viber: account data and IP address used to create the account; investigators can also access message history (date, time, source, destination).
WeChat: basic data such as name, phone number, e-mail and IP address, but only for non-Chinese users.
WhatsApp: the targeted person’s basic data, address book and contacts who have the targeted person in their address book; it is possible to collect message metadata in real time (“Pen Register”); message content can be retrieved via iCloud backups.
Wickr: Date and time of account creation, types of terminal on which the application is installed, date of last connection, number of messages exchanged, external identifiers associated with the account (e-mail addresses, telephone numbers), avatar image, data linked to adding or deleting.
TL;DR Signal is the messaging system that provides the least information to investigators.
An official FBI document dated January 2021, obtained by the American association “Property of People” through the Freedom of Information Act.

This document summarizes the possibilities for legal access to data from nine instant messaging services: iMessage, Line, Signal, Telegram, Threema, Viber, WeChat, WhatsApp and Wickr. For each software, different judicial methods are explored, such as subpoena, search warrant, active collection of communications metadata (“Pen Register”) or connection data retention law (“18 USC§2703”). Here, in essence, is the information the FBI says it can retrieve:
Apple iMessage: basic subscriber data; in the case of an iPhone user, investigators may be able to get their hands on message content if the user uses iCloud to synchronize iMessage messages or to back up data on their phone.
Line: account data (image, username, e-mail address, phone number, Line ID, creation date, usage data, etc.); if the user has not activated end-to-end encryption, investigators can retrieve the texts of exchanges over a seven-day period, but not other data (audio, video, images, location).
Signal: date and time of account creation and date of last connection.
Telegram: IP address and phone number for investigations into confirmed terrorists, otherwise nothing.
Threema: cryptographic fingerprint of phone number and e-mail address, push service tokens if used, public key, account creation date, last connection date.
Viber: account data and IP address used to create the account; investigators can also access message history (date, time, source, destination).
WeChat: basic data such as name, phone number, e-mail and IP address, but only for non-Chinese users.
WhatsApp: the targeted person’s basic data, address book and contacts who have the targeted person in their address book; it is possible to collect message metadata in real time (“Pen Register”); message content can be retrieved via iCloud backups.
Wickr: Date and time of account creation, types of terminal on which the application is installed, date of last connection, number of messages exchanged, external identifiers associated with the account (e-mail addresses, telephone numbers), avatar image, data linked to adding or deleting.
TL;DR Signal is the messaging system that provides the least information to investigators.
There was a MrBallen video with the same type of story. Some younger woman died of a heart attack while sitting up in her own coffin.
Rebooting a LUKS Encrypted System Without Typing The Passphrase: https://mckinley.cc/blog/20230526.html
I was able to fix this now, by making a ‘default.nix’ file, and then you can open a shell that has all the stuff needed by simply typing ‘nix-shell’ in the root git directory. Pretty nice, I’m starting to enjoy this OS more and more.
Here I am, looking at my bookshelf, where the ‘12 rules for life’ book sits.
I found the way he had to be put in a coma to get off addiction to his medicine etc fascinating. It felt like the good old ‘do as I say, not as I do’ type of thing. But hey - regardless of who you are or how strong you portray yourself - there can always be hard issues to tackle in life.
Isode: Red/Black 2.0 – New Capabilities
This major release adds significant new functionality and improvements to Red/Black, a management tool that allows you to monitor and control devices and servers across a network, with a particular focus on HF Radio Systems. A general summary is given in the white paper Red/Black Overview
Support added for Switch type devices, that can connect multiple devices and allow … ⌘ Read more
type of guy who is a wizard and reads all the cookie warnings and EULAs because he didn’t get this old by ignoring the fine print on demonic contracts
yeah but as you can see I can not type a message properly inside termux XD
evolution lets animals age because otherwise they fall into procrastination type paradox situations
On my blog: Normalizing Image Type and Size https://john.colagioia.net/blog/2023/04/05/file-type-size.html #linux #programming #techtips
go mills() 😅
So. Some bits.
i := fIndex(xs, 5.6)
Can also be
i := Index(xs, 5.6)
The compiler can infer the type automatically. Looks like you mention that later.
Also the infer is super smart.. You can define functions that take functions with generic types in the arguments. This can be useful for a generic value mapper for a repository
func Map[U,V any](rows []U, fn func(U) V) []V {
out := make([]V, len(rows))
for i := range rows { out = fn(rows[i]) }
return out
}
rows := []int{1,2,3}
out := Map(rows, func(v int) uint64 { return uint64(v) })
I am pretty sure the type parameters goes the other way with the type name first and constraint second.
func Foo[comparable T](xs T, s T) int
Should be
func Foo[T comparable](xs T, s T) int
go mills() 😅
So. Some bits.
i := fIndex(xs, 5.6)
Can also be
i := Index(xs, 5.6)
The compiler can infer the type automatically. Looks like you mention that later.
Also the infer is super smart.. You can define functions that take functions with generic types in the arguments. This can be useful for a generic value mapper for a repository
func Map[U,V any](rows []U, fn func(U) V) []V {
out := make([]V, len(rows))
for i := range rows { out = fn(rows[i]) }
return out
}
rows := []int{1,2,3}
out := Map(rows, func(v int) uint64 { return uint64(v) })
I am pretty sure the type parameters goes the other way with the type name first and constraint second.
func Foo[comparable T](xs T, s T) int
Should be
func Foo[T comparable](xs T, s T) int
ICYMI: CodeQL enhancements
Learn about CodeQL’s improved user experience and enhancements that let you scan new languages, detect new types of CWEs, and perform deeper analyses of your applications. ⌘ Read more
decided to boot it again. turns out I typed the wrong encryption password yesterday, and instead of saying that it printed that error. booted fine now :)
K-Means Clustering
⌘ Read more
@prologic@twtxt.net @movq@www.uninformativ.de this is the default behavior of pass on my machine:
I add a new password entry named example and then type pass example. The password I chose, “test”, is displayed in cleartext. This is very bad default behavior. I don’t know about the other clis you both mentioned but I’ll check them out.
The browser plugin browserpass does the same kind of thing, though I have already removed it and I’m not going to reinstall it to make a movie. Next to each credential there’s an icon to copy the username to the clipboard, an icon to copy the password to the clipboard, and then an icon to view details, which shows you everything, including the password, in cleartext. The screencap in the Chrome store is out of date; it doesn’t show the offending link to show all details, which I know is there because I literally installed it today and played with it.
Achtung! The Germans have invaded! At least they seem a bit nicer, even if they type like bots.
so in effect it would look something like this:
---
subject: acct:me@sour.is
aliases:
- salty:me@sour.is
- yarn:xuu@ev.sour.is
- status:xuu@chaos.social
- mailto:me@sour.is
---
subject: salty:me@sour.is
aliases:
- acct:me@sour.is
links:
- rel: self
type: application/json+salty
href: https://ev.sour.is/inbox/01GAEMKXYJ4857JQP1MJGD61Z5
properties:
"http://salty.im/ns/nick": xuu
"http://salty.im/ns/display": Jon Lundy
"http://salty.im/ns/pubkey": kex140fwaena9t0mrgnjeare5zuknmmvl0vc7agqy5yr938vusxfh9ys34vd2p
---
subject: yarn:xuu@ev.sour.is
links:
- rel: https://txt.sour.is/user/xuu
properties:
"https://sour.is/rel/redirect": https://txt.sour.is/.well-known/webfinger?resource=acct%3Axuu%40txt.sour.is
---
subject: status:xuu@chaos.social
links:
- rel: http://joinmastodon.org#xuu%40chaos.social
properties:
"https://sour.is/rel/redirect": https://chaos.social/.well-known/webfinger?resource=acct%3Axuu%40chaos.social
---
subject: mailto:me@sour.is
...
so in effect it would look something like this:
---
subject: acct:me@sour.is
aliases:
- salty:me@sour.is
- yarn:xuu@ev.sour.is
- status:xuu@chaos.social
- mailto:me@sour.is
---
subject: salty:me@sour.is
aliases:
- acct:me@sour.is
links:
- rel: self
type: application/json+salty
href: https://ev.sour.is/inbox/01GAEMKXYJ4857JQP1MJGD61Z5
properties:
"http://salty.im/ns/nick": xuu
"http://salty.im/ns/display": Jon Lundy
"http://salty.im/ns/pubkey": kex140fwaena9t0mrgnjeare5zuknmmvl0vc7agqy5yr938vusxfh9ys34vd2p
---
subject: yarn:xuu@ev.sour.is
links:
- rel: https://txt.sour.is/user/xuu
properties:
"https://sour.is/rel/redirect": https://txt.sour.is/.well-known/webfinger?resource=acct%3Axuu%40txt.sour.is
---
subject: status:xuu@chaos.social
links:
- rel: http://joinmastodon.org#xuu%40chaos.social
properties:
"https://sour.is/rel/redirect": https://chaos.social/.well-known/webfinger?resource=acct%3Axuu%40chaos.social
---
subject: mailto:me@sour.is
...
@xuu@txt.sour.is that doesn’t seem to fit the spirit of the spec, at least by my read (I could be wrong obv). The example on Wikipedia’s webfinger page,
{
"subject": "acct:bob@example.com",
"aliases": [
"https://www.example.com/~bob/"
],
"properties": {
"http://example.com/ns/role": "employee"
},
"links": [{
"rel": "http://webfinger.example/rel/profile-page",
"href": "https://www.example.com/~bob/"
},
{
"rel": "http://webfinger.example/rel/businesscard",
"href": "https://www.example.com/~bob/bob.vcf"
}
]
}
and then the comparison with how mastodon uses webfinger,
{
"subject": "acct:Mastodon@mastodon.social",
"aliases": [
"https://mastodon.social/@Mastodon",
"https://mastodon.social/users/Mastodon"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://mastodon.social/@Mastodon"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://mastodon.social/users/Mastodon"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://mastodon.social/authorize_interaction?uri={uri}"
}
]
}
suggests to me you want to leave the subject/acct bit as is (don’t add prefixes) and put extra information you care to include in the links section, where you’re free to define the rel URIs however you see fit. The notion here is that webfinger is offering a mapping from an account name to additional information about that account, so if anything you’d use a "subject": "acct:SALTY ACCOUNT_REPRESENTATION" line in the JSON to achieve what you’re saying if you don’t want to do that via links.
@prologic@twtxt.net That was exactly my thought at first too. but what do we put as the rel for salty account? since it is decentralized we dont have a set URL for machines to key off. so for example take the standard response from okta:
# http GET https://example.okta.com/.well-known/webfinger resource==acct:bob
{
"links": [
{
"href": "https://example.okta.com/sso/idps/OKTA?login_hint=bob#",
"properties": {
"okta:idp:type": "OKTA"
},
"rel": "http://openid.net/specs/connect/1.0/issuer",
"titles": {
"und": "example"
}
}
],
"subject": "acct:bob"
}
It gives one link that follows the OpenID login. So the details are specific to the subject acct:bob.
Mastodons response:
{
"subject": "acct:xuu@chaos.social",
"aliases": [
"https://chaos.social/@xuu",
"https://chaos.social/users/xuu"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://chaos.social/@xuu"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://chaos.social/users/xuu"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe"
}
]
}
it supplies a profile page and a self which are both specific to that account.
@prologic@twtxt.net That was exactly my thought at first too. but what do we put as the rel for salty account? since it is decentralized we dont have a set URL for machines to key off. so for example take the standard response from okta:
# http GET https://example.okta.com/.well-known/webfinger resource==acct:bob
{
"links": [
{
"href": "https://example.okta.com/sso/idps/OKTA?login_hint=bob#",
"properties": {
"okta:idp:type": "OKTA"
},
"rel": "http://openid.net/specs/connect/1.0/issuer",
"titles": {
"und": "example"
}
}
],
"subject": "acct:bob"
}
It gives one link that follows the OpenID login. So the details are specific to the subject acct:bob.
Mastodons response:
{
"subject": "acct:xuu@chaos.social",
"aliases": [
"https://chaos.social/@xuu",
"https://chaos.social/users/xuu"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://chaos.social/@xuu"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://chaos.social/users/xuu"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe"
}
]
}
it supplies a profile page and a self which are both specific to that account.
@abucci@anthony.buc.ci did you know about the chip inside USB-C cables?

https://connectorsupplier.com/usb-type-c-what-you-need-to-know/
some groups have created their own chips that have hidden keyloggers that can phone home over network connections.
@abucci@anthony.buc.ci did you know about the chip inside USB-C cables?

https://connectorsupplier.com/usb-type-c-what-you-need-to-know/
some groups have created their own chips that have hidden keyloggers that can phone home over network connections.
PEP 702: Marking deprecations using the type system
This PEP adds an @typing.deprecated() decorator that marks a class or function as deprecated, enabling static checkers to warn when it is used. ⌘ Read more
@prologic@twtxt.net see where its used maybe that can help.
https://github.com/sour-is/ev/blob/main/app/peerfinder/http.go#L153
This is an upsert. So I pass a streamID which is like a globally unique id for the object. And then see how the type of the parameter in the function is used to infer the generic type. In the function it will create a new *Info and populate it from the datastore to pass to the function. The func will do its modifications and if it returns a nil error it will commit the changes.
The PA type contract ensures that the type fulfills the Aggregate interface and is a pointer to type at compile time.
@prologic@twtxt.net see where its used maybe that can help.
https://github.com/sour-is/ev/blob/main/app/peerfinder/http.go#L153
This is an upsert. So I pass a streamID which is like a globally unique id for the object. And then see how the type of the parameter in the function is used to infer the generic type. In the function it will create a new *Info and populate it from the datastore to pass to the function. The func will do its modifications and if it returns a nil error it will commit the changes.
The PA type contract ensures that the type fulfills the Aggregate interface and is a pointer to type at compile time.
one that i think is pretty interesting is building up dependent constraints. see here.. it accepts a type but requires the use of a pointer to type.
https://github.com/sour-is/ev/blob/main/pkg/es/es.go#L315-L325
one that i think is pretty interesting is building up dependent constraints. see here.. it accepts a type but requires the use of a pointer to type.
https://github.com/sour-is/ev/blob/main/pkg/es/es.go#L315-L325
Ignite Realtime Blog: Spark 3.0.1 Released
The Ignite Realtime community is happy to announce the release of Spark 3.0.1 version.
This release contains mostly fixes. macOS now uses the default FlatLaf LaF. The user can also choose the type of tabs “scroll” as in Spark 3.0.0 or “wrap” as in Spark 2.X. See screenshot below. And also for some users, Spark not saved history.
… ⌘ Read more
$name$ and then dispatch the hashing or checking to its specific format.
Hold up now, that example hash doesn’t have a
$prefix!
Well for this there is the option for a hash type to set itself as a fall through if a matching hash doesn’t exist. This is good for legacy password types that don’t follow the convention.
func (p *plainPasswd) ApplyPasswd(passwd *passwd.Passwd) {
passwd.Register("plain", p)
passwd.SetFallthrough(p)
}
https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L28-L31
$name$ and then dispatch the hashing or checking to its specific format.
Hold up now, that example hash doesn’t have a
$prefix!
Well for this there is the option for a hash type to set itself as a fall through if a matching hash doesn’t exist. This is good for legacy password types that don’t follow the convention.
func (p *plainPasswd) ApplyPasswd(passwd *passwd.Passwd) {
passwd.Register("plain", p)
passwd.SetFallthrough(p)
}
https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L28-L31
$name$ and then dispatch the hashing or checking to its specific format.
Here is an example of usage:
func Example() {
pass := "my_pass"
hash := "my_pass"
pwd := passwd.New(
&unix.MD5{}, // first is preferred type.
&plainPasswd{},
)
_, err := pwd.Passwd(pass, hash)
if err != nil {
fmt.Println("fail: ", err)
}
// Check if we want to update.
if !pwd.IsPreferred(hash) {
newHash, err := pwd.Passwd(pass, "")
if err != nil {
fmt.Println("fail: ", err)
}
fmt.Println("new hash:", newHash)
}
// Output:
// new hash: $1$81ed91e1131a3a5a50d8a68e8ef85fa0
}
This shows how one would set a preferred hashing type and if the current version of ones password is not the preferred type updates it to enhance the security of the hashed password when someone logs in.
https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L33-L59
$name$ and then dispatch the hashing or checking to its specific format.
Here is an example of usage:
func Example() {
pass := "my_pass"
hash := "my_pass"
pwd := passwd.New(
&unix.MD5{}, // first is preferred type.
&plainPasswd{},
)
_, err := pwd.Passwd(pass, hash)
if err != nil {
fmt.Println("fail: ", err)
}
// Check if we want to update.
if !pwd.IsPreferred(hash) {
newHash, err := pwd.Passwd(pass, "")
if err != nil {
fmt.Println("fail: ", err)
}
fmt.Println("new hash:", newHash)
}
// Output:
// new hash: $1$81ed91e1131a3a5a50d8a68e8ef85fa0
}
This shows how one would set a preferred hashing type and if the current version of ones password is not the preferred type updates it to enhance the security of the hashed password when someone logs in.
https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L33-L59
I made a thing. Its a multi password type checker. Using the PHC string format we can identify a password hashing format from the prefix $name$ and then dispatch the hashing or checking to its specific format.
I made a thing. Its a multi password type checker. Using the PHC string format we can identify a password hashing format from the prefix $name$ and then dispatch the hashing or checking to its specific format.
@carsten@yarn.zn80.net what type of NAS? I just upgraded my oooold (~2008) Drobo to a Synology. I have been impressed with all the neat stuff it can do.
@carsten@yarn.zn80.net what type of NAS? I just upgraded my oooold (~2008) Drobo to a Synology. I have been impressed with all the neat stuff it can do.
<author> from <entry>s to <feed>, Newsboat marked all old affected articles as unread. IDs were untouched, of course. Need to investigate that. Had something similar happen with another feed change I did some time ago. Can't remember what that was, though.
Great, last system update broke something, building from current master I get:
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: unknown type [0x13] section `.relr.dyn'
What the heck!?
And it also appears that I’m not really able to reproduce this unread bug. It only kind of works a single time. And it has something to do with my config. Not sure what it is yet. I also noticed that the <updated> timestamps in the entries somehow shifted between the old and new feed. Da fuq!?
Announcing Docker Hub OCI Artifacts Support
We’re excited to announce that Docker Hub can now help you distribute any type of application artifact! You can now keep everything in one place without having to leverage multiple registries. Before today, you could only use Docker Hub to store and distribute container images — or artifacts usable by container runtimes. This became a […] ⌘ Read more
Gajim: Gajim 1.5.2
Gajim 1.5.2 brings another performance boost, better emojis, improvements for group chat moderators, and many bug fixes. Thank you for all your contributions!
Generating performance profiles for Gajim revealed some bottlenecks in Gajim’s code. After fixing these, switching chats should now feel snappier than before.
Did you know that you can use shortcodes for typing emojis? Typing :+1 for example will ope … ⌘ Read more
Look, sir, I know Angua. She’s not the useless type. She doesn’t stand there and scream helplessly. She makes other people do that Look, sir, I know Angua. She’s not the useless… - Quotes from Terry Pratchett’s Discworld Books
PEP 698: Override Decorator for Static Typing
This PEP proposes adding an @override decorator to the Python type system. This will allow type checkers to prevent a class of bugs that occur when a base class changes methods that are inherited by derived classes. ⌘ Read more
@abucci@anthony.buc.ci Its not better than a Cat5e. I have had two versions of the device. The old ones were only 200Mbps i didn’t have the MAC issue but its like using an old 10baseT. The newer model can support 1Gbps on each port for a total bandwidth of 2Gbps.. i typically would see 400-500Mbps from my Wifi6 router. I am not sure if it was some type of internal timeout or being confused by switching between different wifi access points and seeing the mac on different sides.
Right now I have my wifi connected directly with a cat6e this gets me just under my providers 1.3G downlink. the only thing faster is plugging in directly.
MoCA is a good option, they have 2.5G models in the same price range as the 1G Powerline models BUT, only if you have the coax in wall already.. which puts you in the same spot if you don’t. You are for sure going to have an outlet in every room of the house by code.
@abucci@anthony.buc.ci Its not better than a Cat5e. I have had two versions of the device. The old ones were only 200Mbps i didn’t have the MAC issue but its like using an old 10baseT. The newer model can support 1Gbps on each port for a total bandwidth of 2Gbps.. i typically would see 400-500Mbps from my Wifi6 router. I am not sure if it was some type of internal timeout or being confused by switching between different wifi access points and seeing the mac on different sides.
Right now I have my wifi connected directly with a cat6e this gets me just under my providers 1.3G downlink. the only thing faster is plugging in directly.
MoCA is a good option, they have 2.5G models in the same price range as the 1G Powerline models BUT, only if you have the coax in wall already.. which puts you in the same spot if you don’t. You are for sure going to have an outlet in every room of the house by code.
Huh… Nope.
HTTP/1.1 200 OK
Content-Length: 407
Content-Type: text/calendar
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag
Permissions-Policy: interest-cohort=()
Content-Security-Policy: default-src 'none'; sandbox
Referrer-Policy: same-origin
Vary: Authorization
BEGIN:VCALENDAR
VERSION:2.0;2.0
PRODID:SandCal
CALSCALE:GREGORIAN
BEGIN:VEVENT
DTSTAMP:20220822T180903Z
UID:bb63bfbd-623e-4805-b11b-3181d96375e6
DTSTART;TZID=America/Chicago:20220827T000000
CREATED:20220822T180903Z
LAST-MODIFIED:20220822T180903Z
LOCATION:https://meet.jit.si/Yarn.social
SUMMARY:Yarn Call
RRULE:FREQ=WEEKLY
DTEND;TZID=America/Chicago:20220827T010000
END:VEVENT
END:VCALENDAR
Huh… Nope.
HTTP/1.1 200 OK
Content-Length: 407
Content-Type: text/calendar
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag
Permissions-Policy: interest-cohort=()
Content-Security-Policy: default-src 'none'; sandbox
Referrer-Policy: same-origin
Vary: Authorization
BEGIN:VCALENDAR
VERSION:2.0;2.0
PRODID:SandCal
CALSCALE:GREGORIAN
BEGIN:VEVENT
DTSTAMP:20220822T180903Z
UID:bb63bfbd-623e-4805-b11b-3181d96375e6
DTSTART;TZID=America/Chicago:20220827T000000
CREATED:20220822T180903Z
LAST-MODIFIED:20220822T180903Z
LOCATION:https://meet.jit.si/Yarn.social
SUMMARY:Yarn Call
RRULE:FREQ=WEEKLY
DTEND;TZID=America/Chicago:20220827T010000
END:VEVENT
END:VCALENDAR
@prologic@twtxt.net odd is it maybe a wrong mime type thing? Should be text/calendar. Some http servers can mistakenly mark them application/octet-stream
@prologic@twtxt.net odd is it maybe a wrong mime type thing? Should be text/calendar. Some http servers can mistakenly mark them application/octet-stream
PEP 697: C API for Extending Opaque Types
Add limited C API for extending types whose struct is opaque, by allowing code to only deal with data specific to a particular (sub)class. ⌘ Read more
@prologic@twtxt.net correct type parameters. 😅
@prologic@twtxt.net correct type parameters. 😅
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate the event store client can load events and apply them using the Load(ctx, agg) method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate the event store client can load events and apply them using the Load(ctx, agg) method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
Progress! so i have moved into working on aggregates. Which are a grouping of events that replayed on an object set the current state of the object. I came up with this little bit of generic wonder.
type PA[T any] interface {
event.Aggregate
*T
}
// Create uses fn to create a new aggregate and store in db.
func Create[A any, T PA[A]](ctx context.Context, es *EventStore, streamID string, fn func(context.Context, T) error) (agg T, err error) {
ctx, span := logz.Span(ctx)
defer span.End()
agg = new(A)
agg.SetStreamID(streamID)
if err = es.Load(ctx, agg); err != nil {
return
}
if err = event.NotExists(agg); err != nil {
return
}
if err = fn(ctx, agg); err != nil {
return
}
var i uint64
if i, err = es.Save(ctx, agg); err != nil {
return
}
span.AddEvent(fmt.Sprint("wrote events = ", i))
return
}
This lets me do something like this:
a, err := es.Create(ctx, r.es, streamID, func(ctx context.Context, agg *domain.SaltyUser) error {
return agg.OnUserRegister(nick, key)
})
I can tell the function the type being modified and returned using the function argument that is passed in. pretty cray cray.
Progress! so i have moved into working on aggregates. Which are a grouping of events that replayed on an object set the current state of the object. I came up with this little bit of generic wonder.
type PA[T any] interface {
event.Aggregate
*T
}
// Create uses fn to create a new aggregate and store in db.
func Create[A any, T PA[A]](ctx context.Context, es *EventStore, streamID string, fn func(context.Context, T) error) (agg T, err error) {
ctx, span := logz.Span(ctx)
defer span.End()
agg = new(A)
agg.SetStreamID(streamID)
if err = es.Load(ctx, agg); err != nil {
return
}
if err = event.NotExists(agg); err != nil {
return
}
if err = fn(ctx, agg); err != nil {
return
}
var i uint64
if i, err = es.Save(ctx, agg); err != nil {
return
}
span.AddEvent(fmt.Sprint("wrote events = ", i))
return
}
This lets me do something like this:
a, err := es.Create(ctx, r.es, streamID, func(ctx context.Context, agg *domain.SaltyUser) error {
return agg.OnUserRegister(nick, key)
})
I can tell the function the type being modified and returned using the function argument that is passed in. pretty cray cray.
@prologic@twtxt.net Error handling especially in Go is very tricky I think. Even though the idea is simple, it’s fairly hard to actually implement and use in a meaningful way in my opinion. All this error wrapping or the lack of it and checking whether some specific error occurred is a mess. errors.As(…) just doesn’t feel natural. errors.Is(…) only just. I mainly avoided it. Yesterday evening I actually researched a bit about that and found this article on errors with Go 1.13. It shed a little bit of light, but I still have a long way to go, I reckon.
We tried several things but haven’t found the holy grail. Currently, we have a mix of different styles, but nothing feels really right. And having plenty of different approaches also doesn’t help, that’s right. I agree, error messages often end up getting wrapped way too much with useless information. We haven’t found a solution yet. We just noticed that it kind of depends on the exact circumstances, sometimes the caller should add more information, sometimes it’s better if the callee already includes what it was supposed to do.
To experiment and get a feel for yesterday’s research results I tried myself on the combined log parser and how to signal three different errors. I’m not happy with it. Any feedback is highly appreciated. The idea is to let the caller check (not implemented yet) whether a specific error occurred. That means I have to define some dedicated errors upfront (ErrInvalidFormat, ErrInvalidStatusCode, ErrInvalidSentBytes) that can be used in the err == ErrInvalidFormat or probably more correct errors.Is(err, ErrInvalidFormat) check at the caller.
All three errors define separate error categories and are created using errors.New(…). But for the invalid status code and invalid sent bytes cases I want to include more detail, the actual invalid number that is. Since these errors are already predefined, I cannot add this dynamic information to them. So I would need to wrap them à la fmt.Errorf("invalid sent bytes '%s': %w", sentBytes, ErrInvalidSentBytes"). Yet, the ErrInvalidSentBytes is wrapped and can be asserted later on using errors.Is(err, ErrInvalidSentBytes), but the big problem is that the message is repeated. I don’t want that!
Having a Python and Java background, exception hierarchies are a well understood concept I’m trying to use here. While typing this long message it occurs to me that this is probably the issue here. Anyways, I thought, I just create a ParseError type, that can hold a custom message and some causing error (one of the three ErrInvalid* above). The custom message is then returned at Error() and the wrapped cause will be matched in Is(…). I then just return a ParseError{fmt.Sprintf("invalid sent bytes '%s'", sentBytes), ErrInvalidSentBytes}, but that looks super weird.
I probably need to scrap the “parent error” ParseError and make all three “suberrors” three dedicated error types implementing Error() string methods where I create a useful error messages. Then the caller probably could just errors.Is(err, InvalidSentBytesError{}). But creating an instance of the InvalidSentBytesError type only to check for such an error category just does feel wrong to me. However, it might be the way to do this. I don’t know. To be tried. Opinions, anyone? Implementing a whole new type is some effort, that I want to avoid.
Alternatively just one ParseError containing an error kind enumeration for InvalidFormat and friends could be used. Also seen that pattern before. But that would then require the much more verbose var parseError ParseError; if errors.As(err, &parseError) && parseError.Kind == InvalidSentBytes { … } or something like that. Far from elegant in my eyes.
To all my feed subscribers: If you are annoyed by the TTS audio or the “Interactions” link, add a “.min” in front of the feed type in the URL. For example https://jlelse.blog/.min.rss. Thanks for following! 😄 ⌘ Read more
Hi, I am playing with making an event sourcing database. Its super alpha but I thought I would share since others are talking about databases and such.
It’s super basic. Using tidwall/wal as the disk backing. The first use case I am playing with is an implementation of msgbus. I can post events to it and read them back in reverse order.

I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
Hi, I am playing with making an event sourcing database. Its super alpha but I thought I would share since others are talking about databases and such.
It’s super basic. Using tidwall/wal as the disk backing. The first use case I am playing with is an implementation of msgbus. I can post events to it and read them back in reverse order.

I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
PEP 696: Type defaults for TypeVarLikes
This PEP introduces the concept of type defaults for TypeVarLikes (TypeVar, ParamSpec and TypeVarTuple), which act as defaults for a type parameter when none is specified. ⌘ Read more
The Chromium super (inline cache) type confusion
In this post I’ll exploit CVE-2022-1134, a type confusion in Chrome that I reported in March 2022, which allows remote code execution (RCE) in the renderer sandbox of Chrome by a single visit to a malicious site. I’ll also look at some past vulnerabilities of this type and some implementation details of inline cache in V8, the JavaScript engine of Chrome. ⌘ Read more
No insurance payout over capsizing of Hong Kong’s Jumbo Floating Restaurant, owner says
Jumbo was insured by a type of policy that covered third-party losses instead of losses to the company, statement by Aberdeen Restaurant Enterprises says. ⌘ Read more
Philippines’ Duterte leaves brutal legacy in presidency marked by drug war, US-China policy flip-flops
The extrajudicial killings of some 8,000 people has ‘opened the floodgates for a type of governance that disregards the rule of law, due process and human rights’, activists say. ⌘ Read more
‘It can create life’: Chinese team claim stem cell breakthrough in mice study
Researchers say they turned one type of stem cell into another that can develop into all types in the body. ⌘ Read more
Top French court rules against burkinis in city pool
The judges blocked Grenoble’s bid to allow all types of swimwear; a change to allow women to bathe topless was not challenged. ⌘ Read more
Häagen-Dazs Hong Kong apologises after banned pesticide found in 2 types of vanilla ice cream products
Centre for Food Safety halts sale of Häagen-Dazs’ pint-sized and bulk-sized vanilla ice cream after Taiwan’s food authorities found ethylene oxide in them. ⌘ Read more
numpy.unique needs the type to be comparable by < and >, not just ==. that seems like overkill.
Masks, Covid-19 test kits, plastic bottles: more than 9,000kg of litter found on Hong Kong’s hiking trails, seashore last year, green group says
Plastic bottles, bottle lids and buoys top three types of rubbish commonly found on seashore, while cigarettes, tissue paper and food packaging dot hiking trails, green group Ecobus says. ⌘ Read more
Gajim: Gajim 1.4.4
Gajim 1.4.4 comes with many improvements: emoji auto-complete, automatic theme switching when your desktop switches from light to dark in the evening, a completely reworked Gajim remote interface, and many bug fixes.
After many emoji improvements in Gajim 1.4.3, this version comes with an emoji auto-complete while writing messages! As soon as you start typing a :, a popover will show you available emoji shortcodes, just like on Slack or Github 🎉
 in the English language, but I’m not convinced.
A new “Pokemon”-type game for the Command Line
Available for Linux, Windows, and macOS. All written in Python. ⌘ Read more
Types of Scopes
⌘ Read more
“Typioca” - A terminal-based typing speed tester
A really, really classy looking one. ⌘ Read more
Type X to self-doubt
Custom Post Type: Comment ?~L~X https://notiz.blog/b/5tX
Custom Post Type: Comment ?~L~X https://notiz.blog/b/5tX
PEP 688: Making the buffer protocol accessible in Python
This PEP proposes a mechanism for Python code to inspect whether a type supports the C-level buffer protocol. This allows type checkers to evaluate whether objects implement the protocol. ⌘ Read more
1970’s BASIC Computer Games compiled for Linux
Remember typing in code from magazines and books? Let’s compile a bunch of those old games for modern Linux. ⌘ Read more
Nix 2.7.0 released
We’re pleased to announce the availability of Nix 2.7.0. It will be
available from
NixOS - Getting Nix / NixOS.
Here are the release notes:
Nix will now make some helpful suggestions when you mistype something
on the command line. For instance, if you type nix build
nixpkgs#thunderbrd, it will suggest
thunderbird.A number of “default” flake output attributes have been renamed.
These are:defaultPackage.<system></system>→packag ... ⌘ [Read more](https://nixos.org/blog/announcements.html#nix-2.7.0)
False Dichotomy
⌘ Read more
Code scanning finds more vulnerabilities using machine learning
Today we launched new code scanning analysis features powered by machine learning. The experimental analysis finds more of the most common types of vulnerabilities. ⌘ Read more
having small “this feels like mdma” type moments during listening to techno & dancing. who knew that ~1000 hours of meditation could have an effect?
there are two types of panpsychism, and they can be distinguished by asking “if i shatter this glass, will it feel pain?”. one answers “yes”, the other answers “no clue, but probably not”
PEP 682: Format Specifier for Signed Zero
Though float and Decimal types can represent signed zero, in many
fields of mathematics negative zero is surprising or unwanted – especially
in the context of displaying an (often rounded) numerical result. This PEP
proposes an extension to the string format specification allowing negative
zero to be normalized to positive zero. ⌘ Read more
从 CPU 角度理解 Go 中的结构体内存对齐
大家好,我是 Go 学堂的渔夫子。今天跟大家聊聊结构体字段内存对齐相关的知识点。
原文链接: https://mp.weixin.qq.com/s/H3399AYE1MjaDRSllhaPrw
大家在写 Go 时有没有注意过,一个 struct 所占的空间不见得等于各个字段加起来的空间之和,甚至有时候把字段的顺序调整一下,struct 的所占空间又有不同的结果。
本文就从 cpu 读取内存的角度来谈谈内存对齐的原理。
01 结构体字段对齐示例
我们先从一个示例开始。T1 结构体,共有 3 个字段,类型分别为 int8,int64,int32。所以变量 t1 所属的类型占用的空间应该是 1+8+4=13 字节。但运行程序后,实际上是 24 字节。和我们计算的 13 字节不一样啊。如果我们把该结构体的字段调整成 T2 那样,结果是 16 字节。但和 13 字节还是不一样。这是为什么呢?
”`
type T1 struct {
f1 int8 // 1 byte
f2 int64 // ... ⌘ [Read more](https://gocn.vip/topics/20967)```
Eagle-eyed folks may have noticed that I made a few wee changes to this website.
The biggest, and most noticeable one is that I’ve filtered out all of the like type posts from appearing on the main feed, from rss, and in the archives. There were waaaaay to many, so filtering them out makes the entire website a lot more navigable. They are not gone, though, and I’ll probably keep sharing like type posts, but now they ar … ⌘ Read more
I just went to type the phrase “I avoid Linux like the plague” but then remembered that we’ve all learned that most people won’t actually go much out of their way to avoid the plague.
平凯星辰获评《金融电子化》2021 金融业新技术应用创新突出贡献奖
近日,《金融电子化》杂志社发布了 “2021 第十二届金融科技应用创新奖” 评选结果,平凯星辰(北京)科技有限公司(以下简称 “平凯星辰”)榜上有名,这是对平凯星辰在金融科技领域的创新成果与能力的充分肯定。

Day 16 of Advent of Code is so confusing that I will not finish today’s puzzle. I wonder if yesterday was my last day with Advent of Code, or will the puzzles become more understandable and easier again in the next few days? Maybe I’m just more the practical type. I like programming, but such complex algorithms are not really my thing. And in the end, Advent of Code is supposed to be fun… ⌘ Read more
go 1.18 泛型初体验
go 1.18 泛型初体验go.1.18beta 版发布,众所周知这个 go.1.18 版本会默认启用 go 泛型。这个版本也号称 go 最大的版本改动。
初识 golang 的泛型我们写一个 demo 来看看 go 的泛型是长啥样
”`
package main
import (
<span class="s">"fmt"</span>
)
type OrderTypesRead more”`
PEP 677: Callable Type Syntax
This PEP introduces a concise and friendly syntax for callable types,
supporting the same functionality as typing.Callable but with an
arrow syntax inspired by the syntax for typed function
signatures. This allows types like Callable[[int, str], bool] to
be written (int, str) -> bool. ⌘ Read more
On the blog: Amateur Stenography https://john.colagioia.net/blog/2021/11/28/steno.html #education #technology #opensource #typing
** Operators in C **
Following up my notes on Data Types and Variables in C here are notes on operators in C.
An operator is a symbol that represents a mathematical or logical operation. An operator effects operands.
C provides a number of operators.
Some arithmetic operators include,
”`hljs plaintext
+*
/
%
”`
% is the most exciting of the list, it is called modulo and it returns the remainder after division. Of note, modulo c … ⌘ Read more