North Meets South Web Podcast

In this episode, Michael and Jake catch up on life and code. They talk about fatigue, seasonal shifts, lawn adventures, and the return of hay fever.

We dive into replacing a legacy Salesforce integration with Saloon, frustrations with mocks, and how Saloon fakes have improved testing workflows. Michael walks through his experiments with AI tools like Claude and opencode to prototype fake gateways - treating AI as a “junior dev” pair. The discussion covers gateway patterns, middleware, registry-based response handling, and strategies for testing Salesforce without polluting production environments.

From weeds and soil temps to software fakes and AI-driven dev, this one’s a mix of everyday life and practical engineering insights.

Show links

Creators and Guests

Host
Jake Bennett
Christ follower, software dev @wilbergroup using @laravelphp. Co-host of @northsouthaudio and @laravelnews with @michaeldyrynda
Host
Michael Dyrynda
Dad. @laravelphp Artisan. @LaraconAU organiser. Co-host of @northsouthaudio, @laravelnews, @ripplesfm. Opinions are mine.

What is North Meets South Web Podcast?

Jake Bennett and Michael Dyrynda conquer a 14.5 hour time difference to talk about life as web developers

-Hey. I'm Michael Dyrynda.
-And I'm Jake Bennett.

And welcome to episode 182 of the North
Meet South Web podcast.

-Chuka, chuka, chuka.
-Let's j-

-Hey.
-Let's just assume you heard it. I don't

know why you don't hear it anymore, but it
definitely played.

I have no idea. It's, yeah, it's fine.
It's fine. Hey, everybody. Welcome to

episode 182. We're going to skip the chit
chat. Do you know why? Do you wanna know

why? I'll tell you why. I'm starting the
chit chat, but we're gonna skip it.

-Do it.
-I am... Um,

I think I'm entering that stage of life

where you're just perpetually tired, all
the time.

-Mm-hmm.
-I think it's just how it is. I think

there's... I don't think there's any
coming back from it. I think it is just

called life, and I think that's where I'm
at right now. And so I'm like, "You know

what? Let's just get into it." Like,

no need to, uh, you know, pretend like,
uh, we've got limitless energy here. Like,

let's get down to the nuts and the bolts.
But

that'd be missing one of my favorite parts
of the show-

This has been two weeks in a row that this
has-

... which is catching up with you,
Michael. How are things going, my friend?

This is, this is two weeks in a row that
you've been, like, tired, tired. Which is

-very unusual. So-
-Dude, it is. I think it... Well, I think

-it's going back to the school thing.
-It could be something, like, it could be

-seasonal.
-I think it's the changing of the weather.

-Yeah.
-Yeah. I think that may be what it is.

-Yeah, that's what it is.
-I am... We, we had like this pocket... So,

we're heading into spring now, and, uh,
Australians, we just say like the first of

September is spring. We don't, we don't
hang around for like the spring equinox or

whatever the heck. You know, it's not the
22nd of September. We start all of our

seasons on the 1st of the month. When
they- You know, on the q- on the quarter

that they roll around in.

-Respect. Respect.
-So we're heading into spring now, and, um,

we... Because it's spring, it's like sun
but it's also rainy. But then it's cold,

but then it's sunny, but it's not warm.
And so I had this pocket of time on the

weekend where I was like, "I gotta mow the
lawn now 'cause the weeds are getting out

of control." And

I'm gonna do it so that when the lawn
stuff... Which I just shared a photo of

the, the box that this came in in, in the
cash money. From that-

-Oh, okay then.
-It's a local company called Lawn Hub.

-Mm, nice.
-Which sounds-

-Good name
-... similar to another thing that is also

-a hub, and their branding-
-Oh, sure. Yeah, GitHub.

-Their branding-
-Yeah, sure. Yeah.

Yes. Yes, definitely. Um, and their
branding matches color. Like, all of the

-naming of stuff is-
-Oh my

... is very much in line with the other
hub.

-Mm, mm.
-And so, lawnhub.com.au. So I've, I've got

their stuff

had come in today, and so I had to mow the
lawn because you're not supposed to,

like, spray... I've got this spray stuff.
You're not supposed to fertilize the lawn

or do any of that kinda stuff within 48
hours, or 24 hours, whatever it is, of

-mowing 'cause you wanna catch the weeds-
-Okay

-... as they're in their growth cycle.
-Gotcha. Sure.

So I did this on Saturday thinking I
better do it now 'cause it's gonna rain

-on Sunday.
-Yep.

And then it didn't rain on Sunday, and it
didn't rain on Monday, and it hasn't so

far rained today but it's supposed to rain
this afternoon and all night today and

-then tomorrow and Thursday. So I've got-
-Gotta put... Yep. You're playing the game.

And, and it's like, okay, so I wanna do

this, and you're supposed to do all of
this lawn care, you know,

in September ahead of the growth period.
And it's like, I need to mow the lawn to

get it ready so that the weeds are growing
to then hit it with not the, not the weed

-killer but this is like a growth stuff.
-Okay, sure.

That is supposed to, like... It's a
wetting agent and, and a fertilizer that's

supposed to

spring the lawn into growth. And of course
the weeds-

-Okay
-... which are also there, and then as the

weeds are growing on day 10, you then hit
it with the weed killer. Now, I don't

-know-
-Interesting

... I don't know how you're supposed to
plan this because how do I know in 10

days, especially with the fits and starts
of spring-

-Yeah, yeah
-... when the rain is gonna come? Because

-you're not supposed to apply this stuff-
-Right before rain or anything like that,

-yeah.
-Um, right before rain, you're not supposed

-to, you know-
-You want it to be dry for a couple of

-days, yeah.
-So I don't know.

-It's tough, right? It's tough.
-So I'm just hoping it works out right.

Yeah. We've got a buddy, I've got a buddy
who does like... He's really big into

lawns and he's like, he goes out in the
spring and he measures his ground soil

temperature.

-Right.
-And so he'll like... If it's before, you

know, if it's before the... You know, you
wanna get your pre-emergent weed control

down between 58 and 61 or something like
that, and if you go, you know, I don't

-know. So anyway-
-Not to that extreme

... I just tell him like, "Hey dude, text
me when you're putting your stuff down."

-That's what I always say.
-Yeah, and I'll do it.

"Just text me when you're putting your
stuff down." And then I'll do it too.

'Cause he lives you know, you know, five
miles away, so I'm like, all right.

-Yeah.
-Chances are if it's, if his soil

temperature is all right, it's, mine's
going to be about there too.

-It'd be about the same, for sure.
-Yeah. Anyway, it's, that's a big help.

-But, uh, anyway.
-So yeah. So, so doing that at the moment,

but like trying to fit it in with, with
the weather is ridiculous.

-Yep, yep.
-And so, because I mowed the lawn even

though it was wet it was still enough to
kick up the pollen and so now hay fever

-season is upon me.
-Oh, hay fever it is. Yep. Here it is.

So, right. So this is my thing. You know,
I wake up in the morning, morning feeling

terrible, not wanting to get out of bed
because my head hurts and my nose is

congested and, and you know, we're back in
that. Fortunately, I know because I did

mow the lawn

and it is that time of year that I'm like
it is just hay fever.

That's what it is, yeah. It's not
something else. Yeah. Yeah, yeah, yeah.

I'm not playing the, the COVID or hay
fever game. So I feel rubbish in the

-morning but Re-
-The COVID or hay fever game.

... Re just

had

septoplasty because she's, like, she's
always had bad sleep. Like she will sleep

-for 12 hours, wake up and still be tired.
-Mm-hmm.

And so, you know, gets to a point where
you finally want to do something about

this. You're not gonna just accept that
this is

what it is. And so she went and saw an
ENT, an ear, nose and throat specialist

and they said, "You know, you are waking
as you sleep

but it's not enough

that you need to start looking at a CPAP."
You know, face mask while you sleep kind

of thing.

-Yep, yep.
-This option of the septoplasty was to go

in and to realign her turbinates because
she had a deviated septum in her nose.

-Ah, okay.
-So they go in there and... Like day

surgery, they go in there with a drill and
they go, you know?

-Oh.
-Do whatever they do and sort it all out.

Oh, nope, nope, nope, nope, nope, nope,
nope.

So it was like day surgery but she was,
you know, she was under for it, of course.

They don't do this while you're awake and
she woke up with-You know, like, no

bruising. They they do it pretty pretty
good these days. Because, you know, we

needed to start mucking around in there
around the place, it's like Oh, yeah. ...

right near the surface. So you would
assume there'd be bruising and stuff, and

I'd have questions to answer for a for a
few days after. Why has your wife got

black eyes and all that kind of stuff.
But, um-

Just stay home, honey. Just stay home.
I'll go do-

-Yeah. So-
-... I'll go do other stuff that you need

-to focus on something else.
-Yeah. So she was like ... She had a week

off work which was which was nice, you
know, took care of the kids. And it was

funny though because I said to her

halfway through Saturday, like, she had
this surgery on on Thursday, and I said to

her halfway through Saturday, I said,
"Look, I know that you had the kids for a

whole week while I was in Denver. However,
you had the kids for a whole school

week where you get them up in the morning,
you take them to school."

-And then you say goodbye. Yes. Yes.
-And you say bye bye, and then you and then

you see them again in the afternoon.

Which, don't get me wrong-

-You have them for a week
-... don't get me wrong, it's still ...

Yeah. But don't get me wrong, it's still

hard work. But there's seven hours out of
the day where they're not there.

-Agreed. Yeah. That's okay. Yeah.
-I had them Saturday. Right? I took them

grocery shopping in the morning. We we got
home at lunchtime, and I'm like, crap. It

is only lunchtime, and they're still
going. Like, they wanna keep going. I'm

like, I

I was so tired at the end of that weekend,
like, more tired than I've ever been.

-That's fine.
-But long, long winded way of saying, like,

maybe you've got sleep problems, and this
is why you're feeling tired.

Maybe. Maybe I do. Yeah. Or or maybe it's
just a seasonal thing too. I don't know.

I'm not sure. That's a that is a fair
question. Um, I do see-

Just don't be telling me it's still a
seasonal thing come December or come March

-if you like.
-Yeah. Okay. Fair enough. Let's let's keep-

You've gotta look into it.

Let's keep checking in. Yeah. Let's keep
checking in on this. We'll see we'll see

what's going on here, and I think that's a
this is a good you know, we'll we'll make

this a recurring section of the of the
show here. So

hey, with that out of the way, I am
actually really interested to hear about

something you've been chatting about with
me recently,

which is some of these fake HTTP stuff.
So, you know, we've talked about this on

the show a number of times, this idea of,
like, this gateway pattern and how we

structure it at Wilbur where, to give you
a quick rundown, we will create a gateway

class which is responsible for newing up a
client, setting up the base URL, any

tokens that would need to be retrieved or
pulled from the config to set up that

client. And then we will have methods that
make calls to endpoints and handle any

specifics around that endpoint, whether
it's caching or whether it's rate limiting

or whether it's, you know, massaging a
response that we get back or have it

handling an erroneous response and all
those things, which is great. But then

what we'll do is we'll, uh, bind that into
in the container, um, and we'll bind that

to, you know, an an interface. Right? And
that interface will be implemented not

only on the HTTP side of things, but also
we'll have a fake that returns

data that we have pulled probably from the
API, gotten a real response, and then

we'll sort of load that into the fake. And
we'll have, um, different responses a la

magic tokens. Right? So, you know, stripe
back in the day, you'd have 4242 gives you

a valid response and 4141 gives you an
invalid CVV, whatever. So we do something

similar to that. But I know that you guys
are big Saloon users, which if you don't

know what that is, listener, uh, you
should definitely go check that out. Sam

Carrey has an amazing package called
Saloon. Very popular nowadays. And I'm

interested to hear kind of what you've
been kicking around with that. So you've

been chatting about it a little bit, and I
wanna get a clear picture of what exactly

it is you're talking about

and if it solves some of the same problems
or or what you got. So go. It's all it's

-all you, my friend.
-Yeah. So, yeah, I

we

we're doing this integration at the moment
where we had, like, some old, old library

that was like, it's long since been
deprecated, no longer maintained. So we

had copied the vendor code into our
application code to integrate with

Salesforce.

And that was, you know, to to push leads
in there, to pull contacts out, things

-like that.
-So it's like a PHP Salesforce SDK sort of

-idea?
-Yeah. Basically. Yeah.

-Is that what it was? Okay. Okay. Sure.
-But it was you know, it was like PHP very,

very PHP

5 code.

-Okay.
-But, yeah, long since unmaintained. And at

some point in the last 18 months, I
think, like, fairly recently, we moved to

using this other library called Forest, f
o r r e s t,

and it allowed us to directly run SOQL, so
Salesforce object query language, I think

-it is.
-Interesting.

-Which is like the the version of SQL, uh-
-Okay

... that you can use to query Salesforce.
And we thought

-Customize the Salesforce. Yeah.
-This'd be a great solution. You know, we

can write the queries ourselves. We can do
it. Um, but there was not really a good

testing layer for it to the point where we
were using mockery and we were creating

mock expectations that, you know, this
method would be called with these

arguments. It would return this stuff. And

the problem with that I mean, number 1,
don't test what you don't own kind of

-thing.
-Oh, yep.

But but number 2, mocks and I know that,
um, JMack has been on an adventure trying

to improve this in, uh, I think, Laravel
specifically,

um, and he's gone off and he's been doing
other things that have come up in the

meantime. But he's been trying to improve
the messaging around when a mock

expectation fails. Because when a mock
expectation fails, it just tells you,

like, mockery underscore some, like, hash
or whatever that it's generated for this

thing. It's saying, expected this, but it
didn't happen.

-Yeah. Yeah. And it's very
-And that's it. Like-

It's not it's not clear at all. The the
error message itself is is horrible. Yeah.

It's horrible. It tells you that the

expectation is not correct, but you don't
know why. And so then what you end up

doing is, like, if you're a, quote
unquote, rule developer, you will go and

fire up xdebug and you would follow
through and look at all these things. If

you're a Laravel developer, you go and
start digging all over the place to see,

like, what was actually in this object.
And and then you're looking, like, what is

diff and whether you're using xdebug or
you're using DD, you still have to look

at, like, what is my expectation and what
is in the thing. And some of these

Salesforce objects are quite large. So
we've got 20 or 30

things in here, and you've got to look at,
like, what's missing, what's added,

what's different. Is it in a different
order? Is it somewhere else in the

-response?
-Yeah. Right. Yeah.

It's it's a whole thing. And so I was I
was poring through the... Saloon docs

a while back for some stuff, and I saw in
there that someone had written

a Salesforce

SDK using Saloon. I thought, "Great. I'm
pulling that in immediately. I don't even

have to read the doc, so I don't need to
know any more about it. It's written with

-Saloon, it's gonna be good."
-Yep.

And what that has

enabled us to do, uh, obviously is to use
Saloon under the hood, which makes testing

so much better because we can use Saloon
fake. We can say, "I'm expecting these

res- requests to go out, I'm expecting
these responses to come back." We can do

Saloon fakes, we can... Like, you know, we
can record fixtures-

-So in the testing layer, you can, yeah-
-In the testing layer

... record pictures and replay them back
out.

-Fantastic.
-Mm-hmm. Yep.

It has improved things a great deal to the
point where like, "Okay, we're gonna

replace this Forest library with the
Saloon SDK." But as part of this, I've

been doing some exploration, which is
like, I guess three-fold into, how do we,

how do we do this kind of stuff with, um,
local development? Like, I don't-

-Yeah, that's the question
-... want to be handing out-

-That is the big question.
-I don't wanna be handing out keys to

people to access Salesforce. Um, we, we
spin up and spin down Salesforce

test environments as needed. Like, we
don't typically keep them around. So, you

-might have-
-Sure

... credentials to do something now, but
that, that environment might be gone at

some point in the future when you come
back to it. Um, obviously we don't wanna

test in production 'cause you end up
littering your Salesforce instance with

all of these test accounts and things like
that. And so I, I started going down the

path of, okay, what does this look like to
actually create a fake? And you and I

have spoken about this, as you said
previously, where maybe you can just call

Saloon fake inside a service provider
somewhere and record some fixtures and do

all this kind of stuff. And so this, this
then led to my second point of ex-

exploration, which was using AI. 'Cause
yeah, I'm a big AI boy now, and I like to

I like to play with stuff. So I've been
using

Claude and I've been, you know, with open
code, which is from the SST guys, um, Dax

and, and Adam who are part of the, the
Terminal Coffee, uh, empire, um, have been

building out this open code thing. Which
is kind of like, it's like Claude Code.

It's a, a Terminal application, but it
allows you to hook into different

providers and access different models
through those providers. So we use GitHub

Copilot, um, which means we can't use
Claude as, as I understand it. Claude is

to access the Anthropic, I think, the
OpenAI, whichever it is, their Claude

-service using their Claude-
-Yeah

... CLI. And then I think Cursor's got one
and, you know, all these other companies

have got one. So what open code allows us
to do is to authenticate against GitHub,

and then we have access to whatever models
we have access to inside of GitHub

Copilot. So I can use Claude to then do
this stuff. So I've been in-

-Interesting
-... planning mode. I spend like 45 minutes

just going through, like, "I wanna do
this, I wanna do this." Like, blah, blah,

blah. You know, come up with whatever we
wanna do. Switch to build mode and say,

"Okay, now go build that." And so what
I've been doing, and it's been literally

days 'cause I'm like feeling my way
through it. I'm not necessarily liking the

output or it's, it's partially
implementing things. So, you know, which I

think anyone that's been using AI for any
period of time knows that this is kind of

the process. Treat it as a junior
developer that you're pairing with, and

that's typically how you're gonna go. So
we have been building out a, a fake

gateway,

as you've done with Stripe, where

in some instances, like if we wanna do a
search for a contact or an account,

there's like, here are the, here are the
key phrases that you pass through. You

know, search for Michael and you'll get
like three results back that are like

-Michael A, Michael B, Michael C.
-Sure.

If you search for Michael Dorinda, it will
return a single result, Michael Dorinda.

Um, and so we've done this. Uh, I, I
reached out to Sam Curry, the author of

Saloon, and I said, "What is the approach?
Like, how do we do this?" And he said,

"You know, there's a few people that have
asked about this recently." And like a day

after I'd asked about it, Alex Six from,
um, Zillow who spoke at Arc on US,

um, he, he had pinged Sam

on X and was like, "Hey,

is this possible?" And so, you know, we
had this conversation about, yeah, we're

exploring this at the moment. And what it
essentially boils down to

is hooking into Saloon's global middleware

and, and putting our own handler in there
that basically looks at, okay, is this

enabled? Is our fake gateway enabled? So
with an environment variable and a conf-

uh, environment variable and a config
switch, you know, if this is enabled-

-Yeah, yeah
-... everything should go through our

-Salesforce mock handler.
-Yeah.

And then the, I've iterated on this a few
times where I've landed with like this

registry patent approach where we just
register all of the, the response handlers

we want. And each response class is then
responsible for providing its own should

handle method. And it will look at the
pending request and say, "Okay, is this to

an endpoint that I'm in of interest of?"
And so we've got 20 or 30 of these at the

moment, and it would just like spin
through them all and go, "Okay, this is a

post request to the contact standard
object endpoint. I'm gonna intercept that

request and I'm gonna return this
response." And so we're then using Faker

to just send back fake data. Um,

and then where you can, you can seed Faker

-with a, with a value, right?
-Okay.

So that you get deterministic

fake data back. So what we do is take all
of-

-I never heard of this.
-Okay. So deterministic data

is where like you are, it's pseudo-random.
Like it is random data, but it will

always be the same random data based on
that seed. So you pass it a number from

like one to whatever the upper limit is
that it supports, and then it will see the

random number generator so that when you
call Faker whatever,

it-Internally, it will process that. You
know, it'll go through its array of 50

names, and if you've got a seed of 3, it
will always return the seventh value from

that list of 50 names for first name.

And then the next time you call it, it
will always return the same value and

then... So then when you are developing
things, if you search for Michael, you're

going to get the same Michael back every
single time on every single machine.

-Because if you-
-Interesting

... are searching for Michael and you get
a different fake value back, you know, in

the UI context, it doesn't make sense, you
know?

-Yeah. Yeah, yeah, yeah.
-But with deterministic seeding, it means,

okay, here is, here is the value that I
want to base all of my random data on, and

it will always do that. So what we do is
we look at the body of that pending

request. We take all of the inputs,

we join them together, and then PHP has
this function called CRC32, which will

take a string and it will compute an
integer value that represents what that

is. And then we pass that value into, um,

into Faker's seed method

so that we're always getting this data
back. And so-

-Interesting
-... we've, we've now built out a fairly

robust, um, implementation that will
always give us, like, pseudo-random data,

but in a consistent way. So, like, if
we're searching for something, you know,

we can, we can build our expectations on
it, we can build tests on it 'cause we

know that, like, the fake data won't
change every time we run the test. We know

that we're always gonna get the same set
of data back. So we can actually write

tests against all of these endpoints with
the fake gateway enabled, knowing that

we're gonna get back this specific data.
That then extends-

-So when you say you seed it, you're not-
-Yes

-... seeding a database.
-We're not seeding a database, no.

'Cause they're not models in your
application.

-No.
-You're seeding the responses that are

gonna come back from your mock handler for
Salesforce.

-Correct. Yeah.
-Yeah, yeah, yeah.

-Uh-huh.
-So it's basically like with Faker, you're

almost creating... I mean, it's not a
database, but it's almost a database

because it's pseudo-random. I mean, it's
deterministic, right? So you're-

-Mm-hmm.
-When I'm hearing you say, like, you're

referencing, like, an ID, it's basically
like you're referencing an ID in a

database that actually does not exist
because it's just seeded-

-Correct. Yeah.
-You know, seeded fake data, essentially.

-So-
-Wow. Yeah

... you could think of it almost as a

sort of database, I suppose. I mean, it's
not a database, but, like,

same idea, right? Where it's
deterministic, you can write tests against

-it 'cause it's not gonna change.
-Right.

So it's almost seeded data, but you don't
have models backing this stuff.

-Correct.
-So you have to use some other sort of

-mechanism to do so.
-Yeah.

-Okay.
-So you're, you're seeding the random

number generator that PHP uses, which is
using, like-

-Yep. Yep, yep
-... MT Rand or whatever under the hood.

Yeah. MT... Like, it's a PHP function
under the hood. So if you always want to

get the... This is quoting from the Faker
docs. "If you want to always get the same

generated data, for instance, when using
Faker for unit testing purposes, the

generator offers a seed method which seeds
the random number generator." And the

crux of that is that calling the same
script twice with the same seed produces

the same results.

-Interesting. Okay.
-And this, and this-

-Okay
-... is then why it becomes helpful in, in

the... Like, in a, in a UI context where
if you are seeding based on the inputs, no

matter what you put in there... Like, if
I put Jake in there

or I put Michael in there or I put Eric in
there or I put Sam in there or whatever,

as long as the inputs match, you will
always get the same results back, which

makes the testing a bit more predictable.
If you hand that off to a QA team or, you

know, for testing, or manual whatever, you
know that you, that it's... Like, it's

not gonna make people stop and think,
"Wait, what happened there? 'Cause I got

two different results back." It's like,
no, if I search for Jake-

-Yeah, I guess, yeah
-... the same set of results come back.

Right. So it's like you only... The only
benefit that you lose of fake data is that

the randomness of it is sometimes a bit
of a fuzz test against, you know, can your

code handle values that are not typical
sort of deal?

-Yeah.
-Right?

-Yeah.
-And so that, that's part of the idea of,

like, Faker, which is like, "Hey, it
should be able to generate any value and

it should always work." But it's like,
there are other considerations to be made

too, and so you're just making a
trade-off. You're saying, "Well, we're

okay with losing some of the benefit of
that randomness for the predictability of

having deterministic values that are
getting seeded in here," and for all the

other me- reasons you mentioned.
Interesting.

-Yeah.
-I've never actually heard of this, so

-I'll, I'll check into that.
-Yeah.

-That sounds really cool.
-And so in, in the context of, like,

actually opening up the application in the
browser and, like, using it, I think it

-makes-
-Yeah, yeah

... much more sense than having totally
random data.

-Mm-hmm.
-Because if you think about it, if I'm, if

I'm hitting Salesforce and searching for
Jake, well, I expect-

-Yeah
-... Jake's data to always come back. I

-wanna see-
-Absolutely, yeah

... the same results. And so that's where
this comes in. And, like, this stuff has

been in Faker, I don't know, since
forever. And the reason that, like, I'm,

I, I know this fancy word, deterministic,
is 'cause I built this, um, avatar

generator for Laracon AU, where I wanted
it to be random, but I wanted it to always

be the same for a given input. So if I'm
gonna generate an image-

Yeah, it's, it's almost like functional,
right? I mean, it's f- it's almost like

functional programming where it's like
given the same inputs, you should expect

-to get the same outputs every time. Yeah.
-Yeah. Yeah.

Um, and so, yeah, that, that, that has
worked really well in that context and

provides us, like, much more useful
output. I'm, I'm not sure... I still need

to do a little bit of finagling to make
sure that I'm actually happy with

-what has been built. Because-
-Yeah

... largely it has been just, like,
driving the AI and letting it come up-

-Yep, yep
-... with stuff and fixing things as they

come. But it's, it's been pretty good in
terms of

building the code,

finding problems. Like, I've got it into
this loop now where we put into our Claude

file,

um,

you know, make sure that you always run
PHP unit on the test. Make sure you always

run CS Fixer. Make sure you always run
Stan, so if you've introduced any

violations, like, it'll go back and fix
those things as well, which has been very

helpful. Um, so I think the, the code is
robust. I think the, the... Then the third

exploration is, okay, we've built

this thing. Is this something that we
can... I don't know if we can package it

up or if we produce a set of guidelines or
something that go, "Okay, now for the

other things that we want it to
have..."... mock gateways for. You know,

for a lender integration with a bank or
for a provider of, like, you know, Equifax

or something like that where we're doing
these lookups. Well, we- we want the- the

same data to always come back, but we
don't wanna hit Equifax 'cause that cost

-money every time you do that.
-Again, and it will... And like you said,

it's deterministic in a sense. You don't
have to spin up an Equifax-

-Right
-... non-production environment sort of

-deal.
-Correct.

Like, it's like you just get all those
benefits that you're talking about. Now,

there are, you know, there does end up
being some drawbacks, but, I mean, you

know, there's drawbacks with the current
approach. So you just have to... It's the

-trade-off, right?
-Yeah.

-Um, you know.
-So in- in our tests, right, in our tests,

we would still want to- to do this kind of
stuff with actual fake data. And that's

where we'd dip into the Saloon fakes, and
we would use our fixtures and all of that

kinda stuff. In terms of actually using it

-by hand-
-Yeah, yeah

... in the browser, yeah. Then, but- so
then the exploration was, okay, how do I

build this

infrastructure

where I've got, like, a config file? Okay,
okay, here is Salesforce, but now here is

Equifax, here is bank A, here is bank B,
here is lender A, all of these kinda

things. And I just configure them in
there, and they'll register themselves,

and then they'll find, you know, okay,
this is the thing that needs to hit this.

And it all goes into Saloon's global
middleware and whatever needs to- to deal

with any given request. And we can build
these over time. So I think I'm happy

enough with it that I think that it will
work,

and it seems to cover all of the scenarios
that exist currently

until we start using it in practice and
figuring out, okay, how do we

create the next gateway, the next mock,
the next mock, you know, and actually

using it. That will be the determining
factor about if this approach is actually

robust enough to be that flexible across
the board, so.

-Yeah, yeah.
-We'll see. We- we might revisit that in a,

in a few episodes and see if we've made
any progress on it.

Yeah, it's like you're trying to look into
the crystal ball and determine what the

-future's gonna hold, right? It's like-
-Yeah.

It's- it's so funny, like, I... We talked
to... We talked to the dev team about

this, and they're totally on board with
that- that approach where it's like

sometimes you just gotta ship it and see.
You know what I mean? Like, just- just

push the button and, like, you're not
gonna have the final answer. But, like,

we're not building pianos here. Like, we
can go in and change the code. Like, it's

not a big deal. You know what I mean? It's
like it doesn't have to be perfect the

first time. It just has to be good enough
that it's not gonna break everything. And

if it's good enough, then it's like you
can make modifications as you go, right?

Um, but trying to make predictions about
how it's going to be used everywhere, it's

just impossible. And I feel like my IT
team, they are on that train. They're

like, "We have to have all the variables
solved before we push the button." It's

-like, you don't.
-Mm-hmm.

-You don't.
-Mm-hmm.

You just need to have enough information
to make a good decision and then push it

and see what happens and then learn and
move from there. But you can make

decisions and make changes a lot faster
that way than you can hemming and hawing

and waiting around and trying to get the
perfect answer. And it's like you won't

have the perfect answer until you actually
start moving, then you're gonna figure it

out. So, um, but the other part I was
gonna say is, like, this registration

piece that you're talking about where,
like, you're registering all the different

responses and things like that. And I'm
sure you'll find a way to organize this

well, but, like, right now, two things.
Number 1, they're probably tied to actual

-endpoints, I'm guessing.
-Yeah, so the... Each response has its own

should-handle method, and it gets past
the- the pending request object. So it

goes and looks like it... You c- 'cause
then you've got access to the request

itself, and you can figure out, do I need
to intercept this or not? And

depending on what it is, you know,
sometimes it's- it's enough to just look

at

the endpoint. Sometimes we wanna look at
the endpoint and the body and go...

Because then we've got for authentication,
for example, we've got an email, like a

specific email address for a successful
login. We've got a specific email address

for a failed login, a specific email
address for, like, a- an account that

doesn't exist, like all of these kind of
things. So some of it gets a bit grim. Um,

some of these methods have got some

creative regexes that Claude has written
in there.

-Yeah.
-Which may or may not be the most

-appropriate course of action.
-Yeah.

But you... I mean, in- within the context
of each of those response classes, you can

do whatever you want to determine if it
should be handled.

Yeah. And so I guess that's what I'm
trying to figure out is, like, how do you

co-locate the code that's going to be
handling or that's gonna be responsible

for figuring all that out? And I'm sure
it's, like, you can have, like, some class

double, you know, dot op generate or a
class dot op register handlers or

something like that, where you can kind of
just say, like-

-Right
-... for this particular type of response,

we're gonna have a class named this that's
going to be, you know, by convention,

it's gonna match the naming like this, but
it's gonna be called, you know, blah,

blah, blah, response register handlers
class.

-Yeah. Yeah.
-And then, you know, you just call that,

-and there you go. And, and so you can-
-Yeah

... break it up so it's not like some
massive

just config file, essentially. You know,
there's actually some testability even

around your- your registrations and things
like that, if you needed it to be as, uh,

-as sophisticated as that. But-
-Yeah.

-Maybe not.
-At- at the moment, this, like, registry

that we have, it just, like, you

pass it a, a namespaced path, like
app/gateway/sales floor-

salesforce/fake/responses, right? And it
will go and look in there, and it will

look through... Like, it just looks
through all of the files in there. And if,

if it's a non-abstract class and it
implements an interface that we've got on

there, it will then register it

as a, as a handler. And then it will...
And then the

Saloon is then responsible for passing all
of those

things through and figuring out, should I
be intercepting this request? So it is-

-Mm-hmm, mm-hmm
-... it has been done in such a way where,

like, the registry will go and just, like,
discover all of these things

automatically and then just slot them in
there. So definitely don't run it in

-production.
-Right, right.

Because you could be registering, like,
you know...... dozens to hundreds of

classes for all of your Saloon
implementations. Um, but locally, like, it

doesn't matter too much. Our machines are
so overpowered and over-provisioned that-

Totally

... having this do it. No, and especially
if you're just enabling them one by one.

So there's, like, the top level

is this thing that spins through the
config and then registers all the

handlers, and then each handler is
responsible for then going and registering

all of its responses. So if you've got
them all disabled, it'll just spin through

that top level four or five or ten or
however many integrations you've got

fairly quickly, and it'll just do nothing.
Like, we just filter them out of the

collection.

-So-
-Yes

... I would like to share some code in
time once I've-

-Yeah, absolutely
-... you know, happy that it is, it is

actually a sensible approach. But, you
know, early indications, um,

with, like, just the Salesforce

mock, uh, seems to be good. The proof will
be in the pudding of whether or not it

actually extends to other handlers. And
I've been trying to kind of guide the AI

to make sure that this is extensible. And
anytime we start duplicating things, it's

like, "Okay, let's pull this out, let's
hoist this up to the top-level namespace,

let's, you know, make sure this is all
possible." 'Cause it is something that is,

in my mind, that, like, we need to be
able to do this. So, I think the, the main

thing is just... Salesforce is a very

large thing. Like, there's a big surface
area of things that you can do. And so

there's lots of overlap to the same
endpoints. But when you've got discrete

endpoints, it's much easier to have, like,
a common thing that just, like, injects

fake data based on the request kind of
thing, so. I, I, I feel good about it, but

I'm still, um, cautious about

how well that works as we start
integrating more. So we'll see how that

-goes in time.
-That's exciting, dude. Yeah, I'm excited

to hear about that. That's, um, that
sounds really cool. Uh, yeah, so we'll

follow up on that in future shows. A
couple of things I wanted to share real

quick before we wrap this one up. Bond is
a new thing by Filip

Gagnik, Gagniks. I don't know how to say
his last name. Anyway, he's a Livewire and

Alpine dude, and he just released this
library, Bond, uh, which is this

interesting way

to

give you essentially, like, fully
reactive, optimistic UIs on the front end

that are also Livewire-aware. So you get
the best of front-ends, like with

modern JavaScript tooling, like being able
to do includes and things like that,

um, and bundling and

all those, all those pieces,

and then also all the benefits of
Livewire. And so in his demo, that he put

out a video today about this,

um, he goes through and shows with this
counter component, it's fully reactive,

and it's like he can plus, plus, plus,
plus, plus, plus, plus on this counter.

And then in the bottom he has like,
"Here's what the Livewire server rendered

-value is." And you can see-
-Hm

... that on the front end he's able to
click it as fast as he wants and the front

end stays reactive and it doesn't make
those back-end calls, and then it sort of,

like, lazily updates that background,
that background, um, amount. And then when

it makes a round trip, it ends up
updating that, that thing on the front end

as well. Um, but your front end allows
you to continue to go just as fast as the

browser front end will allow you to, as
long

-Yeah
-... as long as the, you know, user's

machine is able to catch up or, you know,
keep up with your JavaScript, uh, front

end interactions. It will take care of
sort of eventually syncing in the back end

-which is really, really cool.
-Mm-hmm.

We've needed this in a couple projects,
and, um, he's got some, uh... It's just

very interesting. It's got TypeScript
support, um,

-super, super cool.
-Interesting.

-So Vite basically will pull out-
-Do you wanna-

-Go ahead.
-You'll have to send me a link so I can put

-it in the show notes.
-Yeah.

-It sounds interesting.
-Yeah, absolutely, I will. And I'll, I'll

send you the, uh, the video that he made
here.

-Mm-hmm.
-It's really, really good. Uh, Wilbur

Powery, uh, talked about it, um, today in
our, in our dev chat. So there's the video

and then I will send you the open source
repo as well. Both look really, really

cool. It's a nine-minute video. You should
definitely check it out. Really well

done. Uh, he seems like he, he essentially
manuscripted his video that he was gonna

do. It's, it's nine minutes and it's just
pure code. Like-

-Nice.
-... doesn't stumble over one word. It's so

well rehearsed. It's the best video on a
new thing that I've seen people, you know,

started to put out in a while. It's
really, really good. So

shout out, Philip. Good job. Secondly, uh,
we've been talking about our journey, uh,

at our company of restructuring a lot of
our roles and permissions and things like

-that.
-Mm-hmm.

And how we've sort of split the
responsibilities between, uh, basically

saying our application's only
responsibility is to check permissions

-with gate checks.
-Yes.

And then what we've done is we have bound
those particular abilities to AD groups.

And we've done that using... In AD, I mean
active directory. We've done that using,

uh, enums and enum attributes, which I
swear is one of the most productive secret

ninja combinations ever. Enums with
attributes is just-

-Mm-hmm
-... awesome. It's so cool. Um, it allows

you to have, like, type safety and also to
bind additional pieces of information

directly next to enums, which I just
absolutely love. So really, really cool

combination. I'm liking that. And I feel
like we've arrived at some conclusions,

um, about how we've found to best
structure some of those things,

specifically regarding, like, departments,
job titles, and stuff like that. So, um,

I'm interested to share some of those
maybe in a couple weeks and-

-Mm-hmm
-... talk about that and some of the

discoveries we've made, and maybe talk
about this Bond thing too. We are-

-Yeah
-... right now in the process of creating a

two-way interactive texting experience
through SMS. So people who wanna get hold

of our agents, they can do so through SMS.
We're using Twilio Conversations.

But...... we're pulling a lot of the
Twilio Conversation stuff local. We're

-saving records on our side.
-Mm-hmm.

Um, Twilio's, like, the source of truth,
but we'll pull those down to our side, so

we have database records then can- can
basically enrich that data with our own

data. Um, and we're using a LiveWire front
end. We're building on a LiveWire front

end, which is great, but this idea of,
like, the optimistic UI is very

-attractive-
-Mm-hmm. Yeah

... because sometimes it does, it can feel
a little bit laggy. You know what I mean?

If you're doing, like, high volume
interactions back and forth, or you're

trying to say, like, "Who's..." You know,
"Which one of our team members is

currently in this conversation?" How are
we able to, you know, using presence

channels or some of those things.
Sometimes it can feel a little bit laggy,

or notifications if a new thing comes in.
You know, you have to kind of loop over-

-Yeah
-... a bunch of stuff in the background.

Anyway, um, I'm interested to see if this
is something we can start using and, um,

since Wilbur Power is the lead on that
project, and he's the one who discovered

this library, I'm interested to see if
this is something we might actually use in

the next couple of weeks as well. So,
looking forward to that in the next show,

-I suppose.
-Yeah. Yeah, so, um, Ash Allen, I think it

was, tweeted something out about putting
methods on enums.

-Okay. Yeah, yeah.
-Um, to, like, to- to return a label for

something. Because, you know, your cases
and your names don't always match up with

what or how you wanna present that to the
user, so he was talking about, you know,

having a ToLabel method for things that
would then return

something that you could just put into
your UI as opposed to what you're storing

in the database. And then someone had put-
mentioned in there that, yeah, you can

create attributes here that target, um,
like, the constants but, you know, enum

members in that case, where you could put
like a pound square bracket label

whatever, and then you've got labels
available through that as well. So, I

think that's a, a, a, as you say, a really
powerful combination and it gives you a

lot of flexibility

across enums, not just... Like, I don't
have to create an, you know, a label

method here or ToLabel and then a map and
then, you know, match the value to

whatever. You can just put it straight
there on the, um,

on the- the enum member itself, and then
you can do it on a case by case basis.

Like, you would expose the label method
directly and would say, like, "Hey, is

there an attribute here?" or return the
value of the attribute. Otherwise, you

might do, like, a string snake or a string
title or whatever it is to, you know,

have some fallback where you wanna do it
that way. So, yeah, I- I-

-Yep. Yep. Really, really powerful combo.
-I do- I do think enums and attributes go

-together like lamb and tuna fish.
-Yeah. Lamb and tuna fish. I've not heard

that. That is a new one on me, and, uh, I
love it. I- I will add it to my list-

-Pretty sure it was from Big Daddy
-... of things that I tell my friends.

-I- I will tell my friends when-
-Big Daddy originals

... when we talk about Australian
colloquialisms. So this is not a, this is

not an Australian thing? Lamb and tuna
fish?

-No.
-Oh.

Lamb and tuna fish was a, it was a
character... Uh, it was Big Daddy. It was

a character that, um,

-uh, Rob Schneider played in that movie.
-Okay, okay.

Where he was... Yeah, he was, he played,
like, you know, as Rob Schneider did back

then, he played like a foreign, non-
nondescript-

-Sure
-... foreign character. And he, yeah-

-It's hilarious.
-I'll put a link in the show notes.

All right, I'll have to check it out. Hey,
what episode are we on? 182?

-That's right.
-182, folks. Thanks so much for hanging out

with us. You can find show notes for this
episode at northmeetsouth.audio/182. Hit

us up on

X or on BlueSky at jacobbennett and
michaeldrinda, or at North Meets... Or,

North South Audio. And of course, if you
liked the show we would really appreciate

it if you'd rate it up in your podcatcher
of choice. Five stars would be incredible.

Thanks, folks. Until next time, we will
see you. Bye-bye.

Bye.